Chapter 9
When the Outside World Goes Wrong
Reproduce Before You Fix
One thing before you start: this chapter’s copy of the catalog project has a bug in it, and we put it there on purpose. It is not something you did wrong in Chapter 8, and it is not a mistake in the seeded files. Debugging is a skill that needs something broken to practice on, so here is something broken.
Your job is to find it the way you would find a real one, which means resisting the urge to start editing.
The catalog command already reports malformed input without a
In the Bash panel, start from the project root and run it:
pwd
python catalog.py catalog.csv selected.json --minimum-quantity 4
cat selected.json
The command writes one item. Chapter 8’s contract says the option keeps items whose quantity is at least the threshold, so an item with quantity 4 and a threshold of 4 should have stayed. Two items were expected.
Do not fix it yet. What you have right now is more valuable than a fix: a reproducible debugging case. You know the directory (/workspace), the exact command, the exact input file, and the exact wrong result. Any of those changing makes it a different case.
That last point is the one people skip. Running a command again only counts as evidence when everything around it stayed the same. A different directory, a different threshold, an edited CSV, and you are now looking at a new problem while believing you are looking at the old one.
Three owners of failure
Run a command with one missing path:
python catalog.py catalog.csv
Argparse prints usage and an error on stderr, then exits with status 2. Conversion never starts. This is an interface failure: the command did not match its public grammar.
Now name an input that does not exist:
python catalog.py missing.csv selected.json
The command matches the grammar, but the outside world cannot supply the requested file. This is an expected external failure. The program understands the failed operation well enough to give a short diagnostic and status 1.
A programming defect is different. Start Python’s interactive prompt:
python
Then ask the selection
>>> import catalog
>>> catalog.select_items([{}], 4)
This produces a traceback ending in KeyError: 'quantity'. The file boundary did not fail. Project code received a shape it claims cannot occur after validation. Turning that into “could not read the catalog” would hide the evidence needed to repair the program.
Leave the interactive prompt before returning to Bash:
>>> exit()
Read the traceback from the result back to the cause
Start at the final line. It gives the KeyError: 'quantity'. Then move upward to the innermost frame in project code. That frame names catalog.py, the line inside select_items, and the
Earlier frames explain how execution arrived there. They are context, not automatically the place to edit. The first useful question is: which innermost project operation violated an assumption?
python catalog.py source.csv prints argparse usage and exits with status 2. Which owner should you investigate first?
A traceback ends in KeyError: 'quantity' and the innermost project frame points inside select_items. What should you inspect first?
Next you will pause the wrong successful run before its comparison and inspect the values that decide whether the boundary item stays.