💻 Coding

Python Traceback Debugger and Root-Cause Fix

Read a Python traceback and code, name the root cause, show a minimal failing case, and propose a patch with tests. No invented frames.

0.0
0Reviews
P
August 24, 2026

Prompt

Act as a Python debugger who reads the traceback as source of truth. Do not invent stack frames, files, or line numbers. Name the first change that would fix the failure, then a test.

Inputs:
- Traceback: [Paste]
- Code: [Relevant files or none]
- Python version: [Version]
- Command that failed: [Command]
- What I expected: [Expected]
- Recent change: [Change or unknown]
- Constraints: [Cannot bump deps / must stay sync / etc.]

Generate:
1. Frame readout: each frame in order, file, line if given, what that line is doing. Mark the frame where the exception is raised. Unknown if Code is missing.
2. Root cause: one paragraph. Exception type, the value that was wrong, why it got there. Separate fact (from traceback) vs assumption.
3. Minimal failing case: 10-20 line script or pytest that reproduces it without the rest of the app. If Code is too thin, write a sketch and label it SKETCH.
4. Fix options (2): (A) smallest patch at the raise site. (B) a better fix upstream. Recommend one. Show a unified-style patch only against files in Code.
5. Tests: 1 regression test that would have caught this. 1 extra edge (empty, None, bad type).
6. If I am wrong: 3 other causes consistent with the traceback if Code is thin.
7. What not to do: catch-all except, silence, or bump a library unless Inputs say so.

Constraints:
- Never add frames that were not pasted.
- Do not blame Unicode or the OS unless the traceback says so.
- No fake GitHub issues or CPython ticket numbers.

Instructions

Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.

Examples

Example Input

Traceback:
Traceback (most recent call last):
  File "scripts/export_waitlist.py", line 18, in <module>
    main()
  File "scripts/export_waitlist.py", line 14, in main
    writer.writerow({"email": row["email"], "created": row["created_at"].isoformat()})
  File "/usr/lib/python3.12/csv.py", line 157, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
KeyError: "created"

Code:
# scripts/export_waitlist.py
import csv, sys
from lib.db import fetch_all
def main():
    rows = fetch_all("select email, created_at from waitlist order by created_at")
    writer = csv.DictWriter(sys.stdout, fieldnames=["email", "created_at"])
    writer.writeheader()
    for row in rows:
        writer.writerow({"email": row["email"], "created": row["created_at"].isoformat()})
if __name__ == "__main__":
    main()
Python version: 3.12
Command that failed: python scripts/export_waitlist.py > out.csv
What I expected: CSV with email and created_at columns, ISO timestamps
Recent change: renamed CSV column from created to created_at in fieldnames, forgot the dict key
Constraints: stay stdlib, keep stdout CSV

Example Output

1. Frame readout
- scripts/export_waitlist.py:18 main() from __main__
- scripts/export_waitlist.py:14 writer.writerow({email, created: isoformat(created_at)})
- /usr/lib/python3.12/csv.py:157 DictWriter.writerow -> _dict_to_list
Raised at csv.py:157 as KeyError: created. No other app frames.

2. Root cause
Fact: DictWriter looked up created and the mapping did not have it (KeyError created).
Fact in Code: fieldnames are email, created_at. The row dict uses created, not created_at.
Assumption: the file you pasted is mid-rename. A KeyError on created means the writer still wanted created (fieldnames on disk when it ran, or a DictWriter extras path). The mismatch is the rename: CSV header and dict keys must be the same string.
row["created_at"].isoformat() itself did not throw, so created_at on the DB row is a datetime, not None.

3. Minimal failing case
import csv, io
buf = io.StringIO()
w = csv.DictWriter(buf, fieldnames=["email", "created_at"])
w.writeheader()
try:
    w.writerow({"email": "a@b.co", "created": "2026-01-01T00:00:00"})
except Exception as e:
    print(type(e).__name__, e)
# If this prints ValueError extras on 3.12, your runtime path is fieldnames still [email, created].
# The production KeyError created is: fieldnames include created, row dict does not.

4. Fix (recommend A)
A (smallest): pass created_at in the dict, matching fieldnames.
-        writer.writerow({"email": row["email"], "created": row["created_at"].isoformat()})
+        writer.writerow({"email": row["email"], "created_at": row["created_at"].isoformat()})
B: keep CSV column created, set fieldnames=["email", "created"] and keep the dict key created. Only if consumers already depend on created.
Recommend A. Matches What I expected.

5. Tests
- Regression: DictWriter with fieldnames email, created_at accepts the patched dict and writes two columns.
- Edge: row["created_at"] is None -> use a guard, isoformat would throw AttributeError next. Not this traceback.

6. If I am wrong
- fieldnames in the running file still ["email", "created"] and someone passed created_at only.
- A wrapper DictWriter subclass.
- Two export scripts, and you pasted the wrong one.

7. What not to do
Do not except KeyError and continue. Do not extrasaction="ignore" (drops a column). Do not pin a different Python to hide it.

Reviews (0)

Please login to leave a review.
Loading reviews...