Promptabide Logo

Find the root cause of a bug before writing any fix

A debugging prompt that makes the AI rank hypotheses, name a confirming experiment and only then propose a minimal fix with a regression test.

At a glance

Best for
Developers stuck on a bug where the obvious patch didn't work, or who want to understand the failure before shipping a fix.
Tested on
Claude · Opus 5.5
You fill in
symptomexpectedcodetried
You get
Symptom, restated An order created at, say, 2026-09-24 01:10 IST (stored as 2026-09-23T19:40:00Z ) is bucketed under 2026-09-23 instead of… (full result below)

Prompt

I have a bug. Do not propose a fix yet.

Symptom: {{symptom}}
Expected: {{expected}}
Code:
{{code}}
Already tried: {{tried}}

Work in this order:
  • 1. Restate the symptom in one sentence, precisely: which input produces which wrong output.

  • 1. List up to 4 hypotheses for the root cause, ranked by likelihood. For each, point to the exact line and explain the mechanism that would produce this exact symptom. "Could be a race condition" is not a mechanism.

  • 1. Check each hypothesis against what I've already tried. Drop any that my attempts rule out, and say why.

  • 1. For the top hypothesis, give the smallest experiment that would confirm or kill it (a log line, a one-line REPL check, a single test) and the result I should see in each case.

  • 1. Only then: the minimal fix for the top hypothesis as a diff, plus one regression test that fails before the fix and passes after.

  • 1. Tell me where else in a codebase this same root cause usually hides, so I can grep for it.


  • If the code shown isn't enough to decide, say what you would need to see instead of guessing.

    Fill in

    {{symptom}}
    What goes wrong, as precisely as you can say ite.g. Orders placed between midnight and 5:30am IST show up under the previous day in the daily report
    {{expected}}
    What should happen insteade.g. Each order is counted on the calendar day it was placed in India
    {{code}}
    The smallest chunk of code that contains the bug, pasted in fulle.g. The groupOrdersByDay function (15 lines)
    {{tried}}
    What you have already tried or ruled oute.g. Checked the DB timestamps are right; setting TZ=Asia/Kolkata on the server changed nothing

    Example input

    symptom: Orders placed between midnight and 5:30am IST show up under the previous day in the daily sales report.
    expected: Each order is counted on the calendar day it was placed in India.
    code:
    ```ts
    // report/groupOrders.ts
    type Order = { id: string; createdAt: string; amount: number } // createdAt e.g. "2026-09-23T20:15:00Z"
    
    export function groupOrdersByDay(orders: Order[]) {
      const buckets: Record<string, Order[]> = {}
      for (const order of orders) {
        const day = new Date(order.createdAt).toISOString().slice(0, 10)
        ;(buckets[day] ??= []).push(order)
      }
      return Object.entries(buckets)
        .sort(([a], [b]) => a.localeCompare(b))
        .map(([day, items]) => ({
          day,
          count: items.length,
          total: items.reduce((s, o) => s + o.amount, 0),
        }))
    }
    ```
    tried: Checked the DB timestamps are correct (stored in UTC with Z). Setting TZ=Asia/Kolkata on the server changed nothing.
    6650

    Generated Outputs (1)

    2 hours ago
    Claude
    Opus 5.5
    Generated Output
    1. Symptom, restated
    An order created at, say, 2026-09-24 01:10 IST (stored as 2026-09-23T19:40:00Z) is bucketed under 2026-09-23 instead of 2026-09-24.

    2. Hypotheses, ranked
  • 1. toISOString() always renders UTC (line 7). IST is UTC+5:30, so every order from 00:00 to 05:29 IST has a UTC date one day earlier. The window you describe is exactly the size of the offset. That's the tell.

  • 1. createdAt sometimes lacks the Z. new Date("2026-09-23T19:40:00") is parsed as local time, which would shift days on some rows. It's less likely, because you confirmed the stored values carry Z.

  • 1. The report UI re-parses day. new Date("2026-09-24") is UTC midnight. Rendered in IST that's still the 24th, so this can't produce your symptom. It would only matter for users west of UTC.


  • 3. Against what you tried
    Setting TZ=Asia/Kolkata changing nothing supports hypothesis 1: toISOString() ignores the process timezone entirely. Hypothesis 2 is ruled out by your DB check.

    4. Confirming experiment
    `bash
    node -e 'console.log(new Date("2026-09-23T19:40:00Z").toISOString().slice(0,10))'
    `
    If hypothesis 1 is right, this prints 2026-09-23, although the order is on the 24th in India. If it prints 2026-09-24, I'm wrong and I'd need to see how the report calls this function.

    5. Minimal fix
    `diff
    +const istDay = new Intl.DateTimeFormat("en-CA", {
    + timeZone: "Asia/Kolkata", year: "numeric", month: "2-digit", day: "2-digit",
    +})
    ...
  • • const day = new Date(order.createdAt).toISOString().slice(0, 10)

  • + const day = istDay.format(new Date(order.createdAt)) // en-CA gives YYYY-MM-DD
    `
    Regression test:
    `ts
    it("buckets a 01:10 IST order on the IST calendar day", () => {
    const [row] = groupOrdersByDay([{ id: "1", createdAt: "2026-09-23T19:40:00Z", amount: 100 }])
    expect(row.day).toBe("2026-09-24")
    })
    `
    It fails on the current code (2026-09-23) and passes after the fix. If you'll ever report for other regions, pass the timezone in as a parameter instead of hard-coding it.

    6. Where the same bug usually hides
  • grep -rn "toISOString().slice(0, 10)" and .split("T")[0]

  • • SQL DATE(created_at) or created_at::date running in a UTC session

  • • "Today's orders" filters built with new Date().setHours(0,0,0,0) on a UTC server

  • • Cron jobs scheduled at "midnight" in server time
  • Why it works

    The line "Do not propose a fix yet" stops the model's reflex to patch the first plausible cause. Asking for a mechanism that produces this exact symptom forces it to match the evidence (here, a 5.5-hour window equal to the IST offset) rather than list generic suspects. Step 3, checking hypotheses against what you already tried, turns your failed attempts into evidence: the TZ change failing is what confirms the diagnosis. The fails-before, passes-after test makes the fix verifiable, and step 6 turns a single fix into a codebase-wide sweep.

    When not to use it

    Skip it for typos and obvious one-line errors, where the ceremony slows you down. It also struggles when the bug depends on state you can't paste: production data, concurrency across services, or a flaky environment. There, gather logs and a reproduction first. For bugs inside a large repo, a coding agent that can run the experiment itself will beat pasting code into chat.
    Comments (0)
    No comments yet. Be the first to share your thoughts!
    Top Creators
    Follow PromptAbide

    New bides, prompt breakdowns and community picks, on whichever feed you already read.

    Trending Tags
    Loading...