AI-Assisted Debugging
On this page
Find and fix bugs faster
Debugging remains an art: understand the symptom, trace it back to the root cause, and fix it without breaking something else. Codex helps with all three steps, but unevenly. On the first step, it adds almost nothing, since you’re the one observing the symptom and knowing what the system should do. On the second, it excels, because tracing a data flow through ten files is systematic reading work—exactly what a machine does better than a tired human. On the third, it provides immediate verification through tests.
Debug from an error
The most straightforward case: you pass the error as-is, without rephrasing or summarizing it.
"The test src/api/routes/orders.test.ts fails with:
TypeError: Cannot read properties of undefined
(reading 'id')
at createOrder (src/services/order.service.ts:42)
Find the cause and fix the bug."
The agent then chains six operations: it reads the test file to understand the scenario, opens order.service.ts at line 42, traces the data flow to find where undefined was introduced, identifies the root cause—missing parameter, typing error, or something else—, proposes and applies the fix, then reruns the test to verify. The third operation is the one that would have cost you twenty minutes of silent reading.
Debug unexpected behavior
Often there’s no error at all: the program quietly does something wrong. These are the most expensive bugs, and the ones where how you phrase your request matters most.
"The POST /api/orders route creates the order in the
database, but the total is always 0. Product prices are
correct in the products table. Find why the total
calculation fails."
This instruction works because it defines the scope: what works, what doesn’t, and one hypothesis already ruled out since the prices in the database are correct. Codex then traces the flow from the HTTP request to the insertion, isolates where the calculation goes off the rails, and proposes a fix. Without the sentence about the products table, it would most likely start by checking exactly what you just checked yourself.
Analyze production logs
You can also start from production traces, simply by pasting the relevant excerpt.
"Here's an excerpt from production logs. The application
intermittently returns 500 on /api/checkout:
[2026-04-01 14:23:01] ERROR: Connection pool exhausted
[2026-04-01 14:23:01] WARN: Query timeout after 30s
[2026-04-01 14:23:02] ERROR: Transaction rollback
Analyze the checkout route code and identify the connection
leak."
Codex connects the three lines—pool exhausted, query timeout, transaction rolled back—, concludes there’s a database connection leak, then searches the code for places where a connection is opened but not properly closed. This is typically a bug that no test reveals, since it only shows up under load and disappears as soon as you try to reproduce it locally.
Debugging by bisection
When the problem is diffuse rather than pinpointed, ask for a methodical investigation instead of a quick fix.
"The TypeScript build fails with 23 type errors since the
last dependency update. Analyze each error, identify whether
it's an API change in a dependency, and fix the code to be
compatible with the new versions."
The value of this phrasing is that it forces a diagnosis error by error. Without the instruction to identify the origin, the temptation for an agent—as for a developer at the end of the day—is to add any until the compiler goes quiet, which turns twenty-three visible errors into twenty-three future bugs.
Effective debugging patterns
The material you provide conditions everything else. Each type of symptom calls for specific evidence to include, and omitting it is like asking for a diagnosis without an exam.
| Symptom | Codex Instruction |
|---|---|
| Failing test | Provide the full error message + the test file |
| Type error | Provide the output of tsc --noEmit |
| Runtime error | Provide the stack trace + steps to reproduce |
| Incorrect behavior | Describe expected vs. observed result |
| Performance issue | Provide metrics (response time, slow queries) |
Prevent future bugs
A fixed bug is only half-handled if nothing prevents it from reappearing elsewhere. So systematically follow up the fix with a consolidation task, formulated from what you just learned.
"The bug came from an unchecked null userId. Add type
guards in all functions in src/services/ that receive a
userId. Also add a regression test for this case."
This second task generalizes the lesson where the fix remained local: the guards cover all services, and the regression test ensures this specific case stays monitored after you leave the project. This is the move that distinguishes a team that fixes bugs from a team that reduces their backlog.
Key takeaways
- Give Codex the maximum context: error messages, stack traces, logs
- Codex traces the data flow to find the root cause
- It verifies its fix by rerunning tests automatically
- After fixing, ask for protections and regression tests
- The more precise your instructions, the faster the debugging