September 12, 2026
READ THE RIGHT LAYER BEFORE YOU ASK AI TO FIX ANYTHING

Last lesson gave you the trail: structured events, request IDs, and three well-designed log entries. This lesson tells you where to look first when the trail goes cold — because every error lives in one layer, and searching the wrong layer wastes hours and invites AI to "fix" healthy code.
The six layers where errors hide
A Research Desk failure can originate in any of these places. Learn the map before you search:
| Layer | Where to look | Typical evidence |
|---|---|---|
| Browser console + network | DevTools console tab, network tab | Failed request, status code, response body, CORS message, request ID |
| Server / function logs | Hosting runtime logs, OBSERVABILITY.md fields | Route event, error class, duration, dependency result |
| Database logs + policy | Database dashboard, policy test output | Permission denied, row-level policy rejection, connection limit |
| Build + deploy logs | Hosting build output, deployment history | Build failure, missing environment variable, crashed start command |
| Provider dashboard + status page | Market-data provider console, model API usage page | Quota exhausted, key revoked, regional outage, latency spike |
| Worker / queue logs | Background job runner, queue depth chart | Job retrying, queue growing, refresh never completing |
The classic beginner mistake is treating all six as one blur: "the app is broken, rewrite the component." The professional move is narrower: *locate, then explain, then change.*
The diagnosis sequence: no rewrite first
Follow this order every time. It is deliberately slow at the start and fast at the end:
reproduce → observe browser request/response
→ capture request ID + time
→ find the matching server event
→ inspect one relevant boundary
→ form a hypothesis → test it
1. Reproduce. Make it happen again with precise steps, or record exactly when it happens intermittently. A bug you cannot trigger on demand is a rumor. 2. Observe the browser request and response. Open the network tab. What URL, method, status code, and body came back? Copy the request ID and timestamp. 3. Find the matching server event. Search server logs for that ID and time. Does the server agree with the browser? Often the browser says "500" while the server says "provider timeout" — now you know the boundary. 4. Inspect one relevant boundary. Identity? Policy? Input contract? Provider adapter? Queue? Pick the boundary the evidence points to, not all of them. 5. Form a hypothesis, then test it. State what you believe, what observation would prove or kill it, and run the smallest check. Only then consider a change — the smallest one.
"Rewrite the feature" never appears in this list. Rewrites destroy the evidence and usually reintroduce the same bug in cleaner-looking code. Class 52 will build the full debugging loop on top of this sequence.
What status codes are actually telling you
HTTP status codes are the server's first hint about which layer to inspect. They guide investigation; they do not complete it:
- 401 Unauthorized — identity problem. Missing, expired, or invalid session. Check sign-in state, session handling, protected-route rules from Class 47.
- 403 Forbidden — policy problem. The user is known but not allowed. Check ownership and authorization policy, not the login form. A 403 on someone else's watchlist item is the system working correctly.
- 400 / 422 — input contract problem. Malformed or invalid data the server refused. Check validation rules and what the frontend actually sent.
- 404 — route or resource problem. Wrong URL, deleted record, or an ID the user should never have seen. Check routing and whether the ID is guessable.
- 429 — rate limit problem. Too many requests too fast. Check quotas, retry loops, and budget caps before raising the limit.
- 500 — unexpected server fault. Something the code did not handle. This is the one that demands the server log — the browser cannot explain it alone.
- Timeout (no status at all) — dependency or network problem. The server waited on a provider, database, or worker that never answered. Check the adapter, provider status page, and queue depth.
Example: a signed-in user saves a watchlist item and gets a 403. A beginner reworks the login screen. The sequence above finds the server event watchlist.edit.denied, owner mismatch in one search — the policy denied a non-owner, exactly as designed. The "bug" was a test using the wrong account.
The bug report that makes AI useful
From Part III you know screenshots can carry context. But a screenshot alone usually hides the request details that matter. Every report needs both the human-visible moment and the machine-readable facts:
- Uncluttered screenshot of the failure state
- Page URL and the exact action taken ("clicked Save on
/brief/AAPL") - Expected result versus actual result, in one sentence each
- Time in UTC and the request ID (or job ID)
- Browser console error text, if any
- Network tab entry: method, URL, status code, response summary
That bundle is what turns an AI assistant from a confident guesser into a genuine investigator. It is also what OWASP's logging and alerting guidance means by an auditable trail: enough linked evidence to reconstruct what happened, without secrets attached. Paste it into this prompt pattern:
Three elements do the work: no-edit forces investigation before patching; rank three hypotheses prevents fixation on the first plausible story; discriminating observation tells you the cheapest next check ("if the server log shows ProviderTimeout for this ID, it is the provider; if it shows AuthzDenied, it is the policy"). Approve the hypothesis before authorizing any change.
Practical exercise: write the one-page report
Take one real or simulated failure in your project and produce a one-page bug report containing: screenshot, URL, action, expected vs. actual, UTC time, request ID, console excerpt, network entry (method/URL/status), the matching server event, the layer you located it in, and your ranked hypotheses with one discriminating observation each.
Finish line: a one-page report with evidence from the correct layer — something another person (or another model) could pick up without asking "what did you actually see?"
Common failure mode: the report says "500 error, probably the database" with no request ID, no timestamp, and no server event quoted. If your report could describe three different bugs equally well, it is not done.
Check your understanding
1. A user gets a 403 saving someone else's Neighborhood Events listing. Which layer holds the answer, and is this a bug? 2. Why does the diagnosis sequence forbid rewriting the feature as a first step? 3. What three things does the no-edit, rank-three-hypotheses prompt buy you that "it broke, fix it" does not?
A located failure is half-fixed. But single incidents are not the whole job — next, you will zoom out to the health of the entire system, and the handful of alerts that tell you something is wrong before your users do.
ARTICLE DISCUSSION
JOIN THE
CONVERSATION.
Got a question, a take, or a better way to do this? Log in and leave a comment.
