Debug Prompts: Why “Fix My Code” Fails (And What to Send Instead)

A bike-rental startup runs a Node.js cron job that syncs live bike counts to its station dashboard every five minutes. It is green in staging. In production it dies roughly twice a day, always around 03:00 and 15:00, with TypeError: Cannot read properties of undefined (reading 'available'). The junior developer on call pastes sixty lines into ChatGPT, types “fix my code, it’s broken,” and gets back a rewritten file that passes syntax checks and fixes nothing.

The problem was never the model. It was the input. A debug request with no error log, no line number, and no environment detail is a coin flip. The model fills the gaps with guesses, and guesses are exactly what you cannot verify at 3 a.m.

The Cost of a Blind Fix Request

When you send code without the failure, the model has two options: rewrite defensively everywhere, or invent a plausible bug. Both look helpful. Neither is a diagnosis. In the cron-job case the naive reply added optional chaining around every property access, which silenced the crash and left the dashboard showing stale counts for the rest of the day. The bug moved, it did not leave.

Debugging is a search problem. A good prompt narrows the search space with evidence: the exact error string, the line it fired on, what changed, and what you already ruled out. A bad prompt hands the model the whole haystack and asks for the needle.

Wrong Prompt vs Right Prompt

Same cron job, same stack. Compare what each request gives the model to work with.

Fix my code, it's broken. Here is my cron job:

const sync = async () => {
  const stations = await fetchStations();
  for (const s of stations) {
    const live = await getLiveCount(s.id);
    s.inventory.available = live.total - live.held;
  }
  await save(stations);
};

It sometimes fails in production. Please fix it
and give me the full corrected file.
Role: senior Node.js debugging partner. Do NOT rewrite the file yet.

Context
- Service: Node 20 cron job (node-cron, every 5 min) syncing live
  bike counts to our station dashboard.
- Stack: Express API, Postgres via Prisma, Redis cache.
- Works in staging; fails ~2x/day in prod, only on the 03:00 and 15:00 runs.

Exact error (production, 3 most recent occurrences)
TypeError: Cannot read properties of undefined (reading 'available')
    at sync (/app/src/jobs/syncInventory.js:14:19)

Relevant code (lines 8-22, with line numbers)
8   const stations = await fetchStations();
9   for (const s of stations) {
10    const live = await getLiveCount(s.id);
11    const held = await getHeldCount(s.id);
12    const total = live?.total ?? 0;
13    const heldTotal = held?.total ?? 0;
14    s.inventory.available = total - heldTotal;
15  }

Already ruled out
- fetchStations() returned 41 rows today, none null.
- Redis TTL is 60s, so stale cache is unlikely.

Ask
1) List the 3 most likely root causes, ranked, each naming the line it implicates.
2) For each, give the one fastest query or log line to confirm or kill it.
3) Do not propose a rewrite until I confirm a cause.

The first prompt asks the model to be a code generator. The second asks it to be a diagnostic partner. That single change in framing decides whether you get a fix or a rewrite.

Why the Second Prompt Finds the Bug

Every line in the right-hand prompt removes a degree of freedom the model would otherwise guess at.

  • The literal error string. Cannot read properties of undefined (reading 'available') tells the model the receiver is undefined, not that the value is wrong. That points straight at line 14, where s.inventory is dereferenced without a guard.
  • The line number. syncInventory.js:14:19 collapses a 200-line file to a single expression. The model no longer scans for plausible bugs; it reads one line.
  • The environment split. “Staging passes, production fails twice a day” is a clue about data shape, not logic. It tells the model to look for a null inventory on specific station rows, not a typo.
  • The ruled-out list. Ruling out the cache and the fetch stops the model from proposing the two most obvious dead ends.
  • The ranked-hypotheses ask. Requesting a cause plus a confirming query turns a vague answer into a testable one.
  • The stop condition. “Do not rewrite until I confirm” keeps the model from burying the diagnosis under a hundred lines of new code.

The likely answer here is that fetchStations() returns a station whose related inventory row was never created, so the join comes back empty only when a new station was onboarded that morning. That is a data bug with a one-line guard, not a logic error. But you only find it quickly when the prompt carries the evidence.

What to Collect Before You Paste Anything

A debug prompt is only as good as the raw material. Before you open the chat, gather six things:

  1. The exact error text. Copy it; do not paraphrase. The phrasing of a runtime error is precise information.
  2. The stack trace line. File and line number are the highest-value characters in the whole request.
  3. The smallest code window. Ten to twenty lines around the failure, with line numbers, beats the whole file.
  4. The environment delta. Where does it pass, where does it fail, and what differs between the two.
  5. Reproduction frequency. “Twice a day” or “every request” changes which bugs are plausible.
  6. What you already checked. A short ruled-out list saves the model from re-deriving your last hour of work.

This is the same discipline behind any structured handoff. If you already keep a habit of asking the model to explain unfamiliar code before you edit it, you can reuse that habit here: describe the runtime behavior first, then touch the code.

A Reusable Debug Prompt Skeleton

Keep this template and fill the blanks. It works for race conditions, null dereferences, flaky tests, and intermittent network failures because it never assumes the cause.

Role: senior {{language}} debugging partner. Do not rewrite yet.

Context
- Service: {{what it does}} running on {{runtime/version}}.
- Stack: {{framework, db, cache}}.
- Works / fails: {{where it passes}} vs {{where it fails}}.
- Frequency: {{how often the failure happens}}.

Exact error (verbatim)
{{paste the full error string and stack trace}}

Relevant code ({{line range}}, numbered)
{{paste 10-20 lines around the failure}}

Already ruled out
- {{what you checked and what it showed}}

Ask
1) Rank the 3 most likely root causes, each naming the implicated line.
2) For each, give one confirming check (query, log, or test).
3) Wait for my confirmation before proposing a patch.

Run it, read the ranked causes, and execute the confirming checks one at a time. When a cause is confirmed, send a short follow-up that says which one it was and ask for the minimal patch only. That two-step rhythm is the whole difference between the rewrite that hid the bug and the guard that removed it. If you want the wider pattern behind this style of back-and-forth, the general debugging workflow is worth reading next, and the same evidence-first habit pays off in your model settings for coding.

Sources & Notes

The prompt patterns here reflect common practice with GPT-4-class coding assistants in 2024–2025. The cron-job example is illustrative; no production system was touched. Evidence-first prompting reduces guesswork but does not replace reading the stack trace yourself. Internal references: Debug Code with ChatGPT: A Workflow, Coding Prompt Examples: Wrong vs Right, Best ChatGPT Settings for Coding.

声明:1.本站所有文章,如无特殊说明或标注,均为本站原创发布。本网站中【文本生成/文生图】使用了DeeSseek人工智能生成内容技术, 算法来源说明:本网站未自行开发、训练或部署深度合成算法,所使用的人工智能算法来自:DeepSeek、Chatgpt、Google Gemini。 2.为了网站加载速度优化,本站预览图片进行压缩处理,所以有些不是太清晰,并不影响AI提示词生图、AI设计等内容。3.任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。--GUUNN.COM