Build1 distinct publisher3 min readUpdated
A developer injected a failure into Formbricks' AI example-response path and found the rollback that was not there: two responses survived, and their survival tripped the zero-response guard.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A developer writing up a bug for DEV's Summer Bug Smash injected a failure into the third write of Formbricks' AI example-response generator, and watched the action reject while the database kept most of what had already happened [s1-c3][s1-c4]. The interesting part is not the orphaned rows. It is that the leftover rows then triggered the feature's own precondition and locked the user out of retrying [s1-c7].
Formbricks is an open-source experience-management platform for surveys and response analysis, and its Survey Summary can generate example responses so a team can look at the analytics before real data exists [s1-c1]. Behind the button, the persistence path is a loop: create a tag, create a display, create a response, evaluate quotas, link the tag, repeat [s1-c2]. Each completed piece could commit before the next one began [s1-c2]. One generation writes a generated-response tag, a Display and a Response per synthetic submission, response timestamps, quota-evaluation links, tag links and extra impression-only Displays [s1-c9]. Production generates 20 of them [s1-c10].
With the failure injected during response 3, the author reports that responses 1 and 2 survived, along with three displays, a newly created tag and two tag links [s1-c4]. The third display had already been written before response creation failed [s1-c5], which leaves one display with no response attached to it [s1-c20]. The enclosing action rejected, but there was no enclosing database transaction capable of undoing the earlier work [s1-c22].
That is a cleanup problem until you add the guard. Formbricks only permits example generation while a survey has zero responses [s1-c6]. After the rate-limit window elapsed, the retry hit that check, and the two surviving responses were enough to fail it [s1-c7][s1-c21]. The operation reported failure, mutated the database, and then cited the mutation as the reason it could not be attempted again [s1-c7].
The framing worth stealing here is the author's: a user-level operation does not become atomic because every helper has a transaction somewhere inside it [s1-c11]. If helper A commits, helper B commits and helper C rolls back, the database has correctly protected three operations, and the user asked for one [s1-c11]. The stated invariant is one request, one persistence outcome: the whole synthetic dataset commits, or nothing from that attempt remains [s1-c8].
The obvious fix did not survive contact. Wrapping persistence in one outer Prisma transaction and passing its client into the writes passed the first rollback test [s1-c15]. Then the author constrained Prisma to a single database connection and the test expired after about five seconds [s1-c16]. The outer transaction held the only connection, while organization, workspace, survey and quota services were still reading through the global Prisma client and asking the pool for a second one that did not exist, so the transaction waited on code inside itself [s1-c17]. A longer timeout would only have lengthened the wait; the boundary had been drawn in one function while the call graph crossed it [s1-c18]. The revised implementation loads stable survey, quota and workspace-to-organization context once through the transaction client [s1-c19].
The reproduction used a deterministic four-response dataset in place of the model call, with the final validation exercising the production-sized batch of 20 [s1-c12], and a baseline characterization test pins the unpatched behaviour [s1-c13]. The author is explicit that this demonstrates a mechanism, not a frequency: it did not come from a production incident report, and the cost is unknown [s1-c14].
What to watch: whether the patch lands upstream, and whether the pattern shows up elsewhere in the same codebase. Any multi-write path guarded by a "only if zero rows exist" precondition has the same failure shape available to it.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Formbricks is an open-source experience-management platform for building surveys and analyzing responses; its Survey Summary can generate example responses so a team can explore the analytics experience before collecting real data.
The AI example-response generator performs a sequence of writes - create a tag, create a display, create a response, evaluate quotas, link the tag, repeat - and each completed piece could commit before the next one began.
The author, writing a submission for DEV's Summer Bug Smash, made the third response fail in order to test the path.
The action rejected exactly as the UI would expect, but underneath it the first two responses were still there, as were three displays, a newly created tag and two tag links.
The third display had been written before response creation failed.
Formbricks only allows example generation while a survey has zero responses.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed first-hand reproduction, single source
The mechanism is described with unusual specificity: an enumerated surviving row set, a deterministic four-response harness with an injected failure at response 3, a linked baseline characterization test, a production-sized 20-response validation, and a second failing test (single-connection pool) that changed the implementation. That is well above assertion-level evidence for the mechanism. It is capped because everything comes from one unaffiliated author on one publisher, with no maintainer confirmation, no independent reproduction and no visible review or merge of the patch.
No adoption evidence in supplied sources
The supplied source contains no release, merge, deployment, pricing, licensing or usage disclosure. It does not state whether the patch was accepted upstream by Formbricks, whether any version shipped it, or how many installations run the affected path. Adoption cannot be measured without inferring facts the source does not provide.
Claims tracked to evidence, slightly under-sold
The headline framing is dramatic, but the body narrows the assertion to exactly what was demonstrated: under a deterministic injected failure the operation left a measured partial state and a later retry failed the zero-response guard. The author volunteers that he does not know production frequency, user count or cost, and that no incident report prompted the work. Because the disclaimers arguably understate a genuinely user-blocking, self-locking failure mode, the gap is marginally negative rather than zero.
Disclosed contest-submission incentive
The piece is openly written as a submission for DEV's Summer Bug Smash, which creates an incentive to find, dramatize and narrate a bug rather than to characterize its real-world importance. That pressure is visible in the framing and in the choice to inject a failure rather than observe one. It is moderated by clear disclosure of the contest, publication of the reproduction and baseline test, and explicit self-limitation on impact claims. No vendor, employer or commercial relationship with Formbricks is evident in the source.
Credible mechanism, unverified reach
Confidence in the mechanism itself is fairly high given the deterministic reproduction, the linked characterization test and the internally consistent second failure under a constrained pool. Confidence in the story overall is held to the middle because the cluster has a single publisher, an incentive-bearing author, no maintainer or upstream confirmation, and no adoption or impact data at all.
build
Prisma v7 stops seeding for you, and the pooled URL will not finish the job1 distinct publisher
build
Your "Index Only Scan" Did 2,847 Heap Fetches: Covering Indexes Are a Vacuum Problem1 distinct publisher
build
The optional EntityManager is the bug: moving the transaction boundary into AsyncLocalStorage1 distinct publisher
build
Three attackers hide behind one connect button, and encryption only stops one of them1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 21, 2026