An error message is evidence
An error usually provides a type, message and stack trace. The stack lists calls involved in reaching the failure. Browser formatting varies, but the question stays the same: which operation failed with which input?
ReferenceError often signals an unavailable name, such as a spelling or scope mistake. TypeError often indicates an operation incompatible with a value, such as calling a non-function. SyntaxError means the source could not be parsed as valid syntax in that context.
Worked example
function getCustomerName(customer) {
return customer.name;
}
console.assert(getCustomerName({ name: "Sara" }) === "Sara");
Calling this function with null would fail at the property access. Inspect the argument first. The failing line is where the problem becomes visible; the missing record may originate earlier.
Guided review
Adding optional chaining can avoid that TypeError, but it may merely move undefined downstream. If a customer is required, validate and report the missing customer. If optional, define what the absence means. The error message cannot choose that business rule.
When reading a stack, begin with your own failing operation and its caller. Do not assume a library frame proves the library is defective. Check what your code passed to it.
Independent exercise
A function parameter is called customer, but its body reads client.name. Predict the error category, the smallest correction and an additional test you would run. Then consider a caller supplying null: is it the same defect?
Correction
Without an outer client binding, the first is a ReferenceError; use the intended parameter name. Test a valid record. Null is a separate contract issue producing a TypeError at property access in the original function. Correcting the spelling does not resolve invalid input handling.
Review
Record the exact error, the triggering input and the relevant call. Avoid replacing all failures with a generic success value: that destroys the evidence needed to repair the program.