{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreihcnixgh4fwkhtwldmrf3r5nm6rdquczwox43ndbrka7svbai3keu",
    "uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpqipjjll462"
  },
  "coverImage": {
    "$type": "blob",
    "ref": {
      "$link": "bafkreia3dzqeqtmb3dierg3umtnjq5ufo6ajb57su2rjcwzuwr32eem6me"
    },
    "mimeType": "image/webp",
    "size": 13720
  },
  "path": "/kevinccbsg/the-production-bug-you-cant-reproduce-by-clicking-1k4d",
  "publishedAt": "2026-07-03T11:40:59.000Z",
  "site": "https://dev.to",
  "tags": [
    "testing",
    "twd",
    "ai",
    "debugging",
    "twd-relay"
  ],
  "textContent": "A payment request showed up in production logs with `country: \"ROW\"` at the top level and `billing_address.country: \"FRA\"` inside the customer object. Two different countries in the same body. The frontend clearly sent it, but nobody could make it happen again.\n\nEvery team has a bug like this. The payload contradicts itself, the logs prove it happened, and no amount of clicking through the app reproduces it. That's usually the signature of a timing bug: something failed, or arrived late, at exactly the wrong moment.\n\n##  Why Manual Testing Can't Touch It\n\nWe tried to reproduce it by hand first. No luck.\n\nThe reason is structural, not lack of effort. To trigger this bug you need one specific API call, the price recalculation that fires when the user changes country, to either fail or respond slowly, at the exact moment the user submits the payment. Manually, you have no lever for that:\n\n  * You can't make the real backend fail once, on demand, for one request.\n  * Browser devtools throttling is global and clumsy: it slows everything, not the one call you care about.\n  * Even if you get lucky once, you can't do it twice. A repro you can't repeat is not a repro.\n\n\n\nSo the bug stays \"unconfirmed\", the ticket goes stale, and the payload keeps showing up in the logs every few weeks.\n\n##  An Agent Reads Code, Not Screens\n\nThis is where the AI agent changed the approach. Instead of guessing from the outside, it read the code and found that the app keeps the country in two places: one in the billing form the user fills in, and one in app state, set when the page first loads. When the user picks a different country, the app fires a background request to update prices, and only when that request succeeds does the app state catch up with the form.\n\nThat gap between \"the form changed\" and \"the app state caught up\" is the whole bug. Two ways to fall into it, found in minutes:\n\n  1. **The background request fails.** The app state keeps the old country, the form shows the new one, and the pay button still works.\n  2. **The user pays too fast.** The payment is built before the background request comes back, so it still reads the old country.\n\n\n\nBoth are timing conditions. Both are exactly the kind of thing you can't produce by clicking. And both are trivial to express as TWD mocks, because in TWD the test controls the server's behavior per request.\n\nThe failure case is one mock:\n\n\n\n    await twd.mockRequest(\"recalcFail\", {\n        url: \"/api/pricing/quote\",\n        method: \"POST\",\n        status: 500,\n        response: { message: \"recalculation failed\" },\n    });\n\n    await selectBillingCountry(\"France\");\n    await twd.waitForRequest(\"recalcFail\");\n\n    await clickSubmitPayment();\n    const rule = await twd.waitForRequest(\"createPayment\");\n\n    // The exact payload from the production logs\n    expect(rule.request.country).to.equal(\"ROW\");\n    expect(rule.request.customer.billing_address.country).to.equal(\"FRA\");\n\n\nNote the assertion: `twd.waitForRequest` returns the intercepted body, so the test checks what the app actually sent over the wire, not what the UI displayed.\n\n##  Reproducing the Race with a Delayed Mock\n\nThe second path needs timing control: the recalculation must succeed, but slowly. TWD mocks accept a `delay`, so the service worker holds the response while the test keeps going:\n\n\n\n    await twd.mockRequest(\"recalcSlow\", {\n        url: \"/api/pricing/quote\",\n        method: \"POST\",\n        status: 200,\n        response: cartResponse,\n        delay: 3000,\n    });\n\n    await selectBillingCountry(\"France\");\n    await clickSubmitPayment(); // pay before the recalculation lands\n\n    const rule = await twd.waitForRequest(\"createPayment\");\n    expect(rule.request.country).to.equal(\"ROW\"); // stale, the store never updated\n\n\nNo `setTimeout` in the test, no flaky sleep, no real backend behaving badly on cue. The race is deterministic because the delay is part of the mock definition. The condition we could never hit manually now reproduces on every single run.\n\nBoth tests passed on the first attempt. Weeks of \"cannot reproduce\" closed in one session.\n\n##  What Made the Difference\n\nTwo things, and neither is magic:\n\n  1. **The agent reads code.** A human reproducing a bug works from the UI inward and has to guess where the timing window is. An agent works from the code outward: it finds the store, the sync mechanism, and the gaps, then writes tests that target them directly.\n  2. **The mock layer makes timing a test input.** Failures and delays are declared per request, in the test file, running against your real app in the browser. That turns \"race condition\" from something you hope to catch into something you specify.\n\n\n\nThe whole loop ran through twd-relay, which drives the browser tab you already have open, so every repro attempt was visible as it executed. After the fix, the same two tests stayed in the suite as regression coverage.\n\nIf you have a ticket that says \"cannot reproduce\" and a log line that says otherwise, this combination is worth trying: let the agent read the code and put the timing in a mock.",
  "title": "The Production Bug You Can't Reproduce by Clicking"
}