cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Reading error messages

Learn what JavaScript error names, messages, and stack traces are telling you so you can find bugs faster and search for help well.

By the end, you can
  • 01
    Name the categoryTell SyntaxError, ReferenceError, TypeError, RangeError, URIError, and EvalError apart.
  • 02
    Follow the breadcrumb trailRead a stack trace from the thrown line back through the calls that led there.
  • 03
    Search like a debuggerTurn a noisy message into a useful query, then check the right docs or line of code.

Errors are clues, not insults

Every developer sees red error text. Beginners often read it as “you failed.” Professionals read it as evidence: what kind of problem happened, the best guess at where it happened, and the chain of function calls that led there.

An error report usually has three useful parts:

  • The name, like TypeError or ReferenceError. This is the category of mistake.
  • The message, like Cannot read properties of undefined. This describes the operation that failed. Messages vary between browsers and runtimes.
  • The stack trace, a breadcrumb trail of function calls, newest first. It helps you jump to the line that actually threw, then trace back to the caller that passed bad data.
Real-life analogyAn error message is a dashboard warning light

A dashboard light does not fix the car, but it narrows the search: brakes, oil, battery, engine. JavaScript errors do the same. The name points to a category; the message points to the failed action; the stack points to where to look first.

In real life: Oil light
In JavaScript: TypeError: wrong kind of value for the operation
In real life: Check engine text
In JavaScript: error.message: the engine’s more specific clue
In real life: Mechanic tracing the hose or wire
In JavaScript: You following the stack trace to your code

Where the analogy stops: A car light cannot tell you the exact code line. JavaScript often can, but minified files, browser differences, and async code can still make stacks imperfect.

Read in this order
  1. Read the error name and message out loud.
  2. Find the first stack frame that belongs to your code.
  3. Open that file, line, and column.
  4. Ask, “What value is this line assuming?”

This lesson builds on strict mode’s idea that mistakes should be loud, and on the console tools you met earlier. The next lesson, Debugging in the browser, will show breakpoints, stepping, and watches. Here we learn the skill that comes first: understanding what the error already says.

SyntaxError, ReferenceError & TypeError

INTERACTIVE

The three errors you will meet constantly are about grammar, names, and values.

Three common JavaScript error families
Error namePlain-English meaningTiny example
SyntaxErrorThe engine or parser cannot read the grammar.JSON.parse("{bad json}") throws while parsing JSON text.
ReferenceErrorA name was used, but no binding with that name exists.console.log(total) when total was never declared.
TypeErrorA value exists, but the operation does not fit that value.undefined.name or calling something that is not a function.

Think of these as different questions: “Can JavaScript read this?”, “Does this name exist?”, and “Can this value do that?” Run the lab below. It catches each thrown error only so the page can show you error.name and error.message. The lesson on try, catch, and finally comes later; for now, treat catch as a safe display case around a thrown error.

Run a real error lab
Error lab sourcePop out in the code editor (opens in a new tab)JavaScript
const demos = {  reference() {    console.log(total);  },  type() {    const user = undefined;    return user.name;  },  range() {    return new Array(-1);  },  uri() {    return decodeURIComponent("%");  },  syntaxAtRuntime() {    return JSON.parse("{bad json}");  },  evalCompatibility() {    throw new EvalError("EvalError still exists");  },}; function inspectError(runDemo) {  try {    runDemo();  } catch (error) {    return {      name: error.name,      message: error.message,    };  }}
Your browser threwReferenceError
error.nameReferenceError
error.messagetotal is not defined

A ReferenceError means JavaScript looked up a name and found no variable, parameter, or global with that spelling.

Try it yourself

ReferenceError: total is not defined

These demos run in your browser. Error messages vary between engines, so trust the name first and read your actual message carefully.

Notice that the name is stable and useful. The message is also useful, but not universal. Chrome and Node often say Cannot read properties of undefined (reading 'name'). Firefox phrases some messages differently. When a test or article relies on an exact message, it should say which engine it describes.

RangeError, URIError & EvalError

SORT

The next three are less common, but they explain many scary-looking messages.

  • RangeError means a number is outside the allowed range. new Array(-1) cannot create an array with a negative length. In Chrome and Node, (1).toFixed(101) says toFixed() digits argument must be between 0 and 100.
  • URIError comes from URI encoding and decoding. A percent sign starts an encoded byte, so decodeURIComponent("%") throws URI malformed.
  • EvalError is mostly historical. Modern JavaScript no longer throws it for ordinary code. It exists for compatibility, and you can still create one with new EvalError("message").
Real-life analogyError types are mistake categories

Sorting the mistake helps you choose the next question. If it is a ReferenceError, inspect spelling and scope. If it is a TypeError, inspect the value. If it is a RangeError, inspect the number you passed.

In real life: Spelling a street that does not exist
In JavaScript: ReferenceError: unknown name
In real life: Using a house key on a bicycle lock
In JavaScript: TypeError: real thing, wrong operation
In real life: Entering floor -1 in an elevator
In JavaScript: RangeError: number outside allowed range
In real life: Writing an address with broken symbols
In JavaScript: URIError: malformed encoded text

Where the analogy stops: Real bugs can involve more than one idea. JavaScript reports the first error it actually hits, not a complete diagnosis of your program.

Sort these real messages by error family. A few messages come from JSON or built-in methods rather than source-code parsing, which is why reading the surrounding line matters.

Match message to error type
  • x is not defined
  • Cannot read properties of undefined (reading 'name')
  • Unexpected token
  • Invalid array length
  • Assignment to constant variable.
  • Unexpected end of JSON input
  • toFixed() digits argument must be between 0 and 100
Try it yourself
0 of 7 correct

Drag each message to the error name that usually owns it. If you are unsure, read the operation hidden inside the message.

Choose a category for every card. You can change an answer at any time; Reset clears them all.
URIError or SyntaxError?
  • URI malformed
  • URIError: malformed URI sequence
  • Unexpected token
  • Unexpected end of JSON input
Try it yourself
0 of 4 correct

These two both come from parsers reading text. Decide whether the text is URI-encoded data or JSON/code grammar.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Reading a stack trace

STEP THROUGH

A stack trace is a receipt for function calls. It lists what was running when the error happened, with the newest call first. The top frame usually answers “where did it throw?” Lower frames answer “who called this?”

Real-life analogyA stack trace is a breadcrumb trail

Imagine walking through rooms and dropping a breadcrumb in each one. When something breaks, the closest crumb is where you are now. The earlier crumbs show how you got there.

In real life: Newest breadcrumb near your feet
In JavaScript: Top stack frame: the thrown line
In real life: Older crumbs lead back home
In JavaScript: Lower frames: callers that led there
In real life: A crumb with a street address
In JavaScript: file:line:column in a stack frame

Where the analogy stops: Stack traces show calls, not intent. The thrown line can be innocent if a caller passed bad data.

Step through this tiny checkout bug. The order has a total, but no discount object. Watch the “Running in” context grow as each function calls the next.

Replay the calls that build a stack trace
Step 0 of 7Ready
Your turn: follow the blue line

Step through the breadcrumb trail. Watch the Running in context grow from script to placeOrder to calculateTotal to applyDiscount.

Running in
  1. script
Next: line 13
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function placeOrder(order) {  return calculateTotal(order);} function calculateTotal(order) {  return applyDiscount(order.total, order.discount);} function applyDiscount(total, discount) {  return total * (1 - discount.rate);} 
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

Now compare that guided replay to a real error.stack string from your browser. The exact text can differ, but the strategy stays the same: read the message, find the top frame in your code, and then inspect the value the line assumed.

Capture a real stack in this browser
Buggy call chainPop out in the code editor (opens in a new tab)JavaScript
function placeOrder(order) {  return calculateTotal(order);} function calculateTotal(order) {  return applyDiscount(order.total, order.discount);} function applyDiscount(total, discount) {  return total * (1 - discount.rate);} placeOrder({ total: 40 });
Captured stacknewest first
TypeError: Cannot read properties of undefined (reading 'rate')
    at applyDiscount (cart.js:10:32)
    at calculateTotal (cart.js:6:10)
    at placeOrder (cart.js:2:10)
    at cart.js:13:1
Try it yourself

The exact wording and stack format can differ. Chrome and Node use at function (file:line:column). Firefox often writes function@file:line:column.

The code runs as predefined source inside a sandboxed iframe, so the function names are the same names shown in the lesson source.

Here is the same idea in a clearly labeled V8-style example. Chrome and Node use this shape. Firefox often writes frames like applyDiscount@cart.js:10:32 instead.

Annotated V8-style stacktext
TypeError: Cannot read properties of undefined (reading 'rate')    at applyDiscount (cart.js:10:32)    at calculateTotal (cart.js:6:10)    at placeOrder (cart.js:2:10)    at cart.js:13:1
  1. TypeError: Cannot read properties of undefined (reading 'rate') The error name and message: start here.
  2. at applyDiscount (cart.js:10:32) Top frame: where the error was thrown.
  3. at calculateTotal (cart.js:6:10) Next frame: who called that function.
  4. at placeOrder (cart.js:2:10) Keep moving down until you find your own code.
  5. at cart.js:13:1 The original top-level call.

Searching for answers

WORKFLOW

Search engines are useful only when your query is clean. Error messages often include your variable names, file names, and data. Keep the reusable phrase; remove your app’s private names.

Buggy code with an app-specific namePop out in the code editor (opens in a new tab)JavaScript
const account = undefined;console.log(account.profile.name);
A practical search recipe
  1. Copy the exact phrase: Cannot read properties of undefined.
  2. Put that phrase in quotes. Add JavaScript only if the results are too broad.
  3. Remove your own names, like account and profile, unless the phrase alone is too vague.
  4. Check MDN’s JavaScript error reference and the docs for the function in the top stack frame.
  5. Make a minimal reproduction: the smallest snippet that still throws. Then rubber-duck it by explaining the values line by line.

A good first query is "Cannot read properties of undefined". After you understand the category, come back to your code and ask the real debugging question: “Why is this value undefined here?”

Where you’ll use this

Error reading is a daily skill. When a page refuses to load, a button does nothing, or a test fails, the fastest path is usually:

  1. Open the console and find the first error after the action you just took.
  2. Read the name and message before changing code.
  3. Jump to the first stack frame in your file, not a browser extension or library bundle.
  4. Inspect the values on that line. Is a name misspelled? Is a property missing? Is a number out of range?
  5. If you still do not know, search the reusable phrase and create a smaller reproduction.
What to check first
You seeFirst questionLikely fix
ReferenceErrorDid I spell and declare this name?Fix the name, import, or scope.
TypeErrorWhat value is actually here?Guard missing data or pass the right shape.
SyntaxErrorWhat parser is complaining?Fix JavaScript grammar or malformed JSON.
RangeErrorWhich number is outside the allowed range?Clamp, validate, or change the argument.

Common misconceptions

“The top stack frame always contains the real bug.”

It contains the thrown line. The real cause may be a caller that passed undefined, an empty string, or a bad number.

“TypeError means I wrote the wrong type annotation.”

Plain JavaScript has no type annotations. TypeError means a runtime value was used in an operation it cannot perform.

“SyntaxError always means the JavaScript file could not start.”

Often yes, but parsers inside functions can throw SyntaxError at runtime too, like JSON.parse("{bad json}").

“If the message differs from a tutorial, I have a different bug.”

Maybe, but engines phrase messages differently. Compare the error name and failed operation first.

“Searching the whole message is always best.”

Remove your private variable names first. Search the exact shared phrase, then add details if needed.

Fun fact

JavaScript’s standard defines error constructors like TypeError and RangeError, but it does not force every engine to use the same English message text.

Practice: read the error before fixing

5 EXERCISES
Exercise 1 · Warm-upPredict the missing-name error

Read the code. What error name does it print?

Starter codePop out in the code editor (opens in a new tab)JavaScript
try {
  console.log(total);
} catch (error) {
  console.log(error.name);
}

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticePredict the range error

    This is not a spelling problem and not a property problem. What error name does the snippet print?

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    try {
      (1).toFixed(101);
    } catch (error) {
      console.log(error.name);
    }

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeFind the throwing function

      In the checkout stack trace, which function is the top frame where the error is thrown?

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      function placeOrder(order) {
        return calculateTotal(order);
      }
      
      function calculateTotal(order) {
        return applyDiscount(order.total, order.discount);
      }
      
      function applyDiscount(total, discount) {
        return total * (1 - discount.rate);
      }
      
      placeOrder({ total: 40 });

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeFix a TypeError caused by a missing property

        Change the object so the program prints a name instead of throwing. What exact name does the solution print?

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const account = {};
        console.log(account.profile.name);

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeDecode a message into a search query

          You see TypeError: Cannot read properties of undefined (reading 'name'). Write the exact phrase you would search first.

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            7 QUESTIONS

            These questions mix concepts with tiny programs. Every wrong answer explains the trap, so use the feedback as part of the lesson.

            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7What is the first thing to read in an error report?

              Choose an answer to see the explanation.

            2. Question 2 of 7What error name does the missing-name snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              try {
                console.log(total);
              } catch (error) {
                console.log(error.name);
              }

              Choose an answer to see the explanation.

            3. Question 3 of 7What error name does the undefined-property snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              try {
                const user = undefined;
                console.log(user.name);
              } catch (error) {
                console.log(error.name);
              }

              Choose an answer to see the explanation.

            4. Question 4 of 7What error name does the JSON parsing snippet print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              try {
                JSON.parse("{bad json}");
              } catch (error) {
                console.log(error.name);
              }

              Choose an answer to see the explanation.

            5. Question 5 of 7In a stack trace, where is the thrown line usually shown?

              Choose an answer to see the explanation.

            6. Question 6 of 7What is the best first search query for Cannot read properties of undefined (reading 'profile')?

              Choose an answer to see the explanation.

            7. Question 7 of 7Which statement about EvalError is accurate?

              Choose an answer to see the explanation.

            Key takeaways

            • Read the error name, then the message, then the stack trace.
            • SyntaxError is grammar, ReferenceError is a missing name, and TypeError is a real value used the wrong way.
            • RangeError means an argument is outside an allowed range; URIError means malformed URI text; EvalError mostly exists for compatibility.
            • Stack traces are newest first. Find the first frame in your code and inspect the value on that line.
            • Search exact reusable phrases in quotes, then check MDN or the docs for the function in the top frame.

            One-line definition.
            An error message is JavaScript’s report of what failed; a stack trace is the breadcrumb trail of calls that led to it.

            Up next: Debugging in the browser.

            Reference snippets used by the testsJavaScript
            console.log(total);const user = undefined;user.name;
            CompleteFrontend Clear concepts. Working examples.