DevTracePad↗
English ⌄
English简体中文日本語

Field notes / Error explainer

A stack trace is a trail, not a verdict

How to turn an exception into a testable explanation without jumping to the first plausible fix.

Start with what actually happened

Copy the exception type, message, and the first frame in code you control. Then include the relevant function and the value that reached it. A stack trace identifies the call path at failure; it rarely proves why an earlier value became invalid. In the ProductList example, the message names an undefined receiver. The adjacent useState() call provides the missing evidence for the initial-render hypothesis.

Keep competing explanations alive

An initial value can be wrong, a response can change shape, or an error branch can assign a different type. These explanations may produce similar symptoms but need different checks. Ask for one observation that would distinguish each hypothesis. “Log everything” is less useful than checking Array.isArray immediately before the failing expression and inspecting the response wrapper. Do this in an environment where sensitive data will not enter logs.

Separate a guard from a fix

Changing products.map to products?.map may hide the crash while leaving an invalid response untreated. Initializing an array may solve the first render but not a later malformed payload. Write down which condition your change addresses. Loading, empty, and failure states deserve separate behavior so that silence does not look like success.

Close the loop with a small matrix

Exercise first render, a valid non-empty response, an empty response, and a failed request. If one of these cannot be tested, record it as unverified. Keep the original failing input beside the changed code. An AI explanation is a plan for investigation; your observed result is the evidence that closes it.

Worked example

Error explainer

Authored example — this fixed result only describes the sample input. It is not a live AI response.

Source

TypeError: Cannot read properties of undefined (reading "map")
 at ProductList (ProductList.jsx:18)
const [products, setProducts] = useState();
return products.map(product => <li key={product.id}>{product.name}</li>);

Annotated result

OBSERVATION
The first render calls .map on products. useState() initializes it to undefined.

LIKELY EXPLANATION
The initial value is not an array. This excerpt supports that explanation; it does not show whether the API later returns a valid array.

NEXT CHECK
Inspect the response shape before setProducts. Is the array the response itself, or response.items?

POSSIBLE CHANGE
Initialize with useState([]), then separately handle loading, empty, and error states. Validate the API response before setting state.

VERIFY
Check first render, an empty response, a populated response, and a failed request. This example has not executed the component.