💻 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.
0Reviews
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 CSVExample 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.