Skip to content
EasyToDecode

How to read a stack trace (Python, JavaScript and Java)

Find the exception type and message first, then the chained cause, then the first frame in your own code. Python lists the most recent call last, so read it from the bottom; JavaScript and Java list it first, so read them from the top.

By EasyToDecode editorial teamPublished October 10, 2026

A stack trace is the record a program prints when an exception is not handled. It tells you three things: what kind of failure happened, a short message describing it, and the chain of function calls that led there. Once you know which part is which, most traces stop looking like noise.

The four parts of a stack trace

Almost every language prints the same building blocks, even though the layout differs.

  • Exception type: the category of failure, such as KeyError, TypeError or NullPointerException. This is often the most useful single word in the whole trace.

  • Message: a short human-readable detail after the type, such as "division by zero" or the name of a missing key or file.

  • Frames: one line (or two) per function call that was active when the error happened. Each frame usually names the file, the line number and the function.

  • Chained exceptions: when code catches one error and raises another, many languages print both. Java labels these "Caused by:", and Python prints a separator sentence between the two traces.

The main trap is order. Some languages list the most recent call last, others list it first. Check which one you are reading before you decide where the problem is.

Python: read from the bottom up

Python starts with the header "Traceback (most recent call last):", so the frame where the error was raised is at the bottom. The Python tutorial explains that the last line "indicates what happened": the exception type, then a detail message. A short sample (synthetic, from a fictional Northgate Invoices script):

Traceback (most recent call last):

File "report.py", line 12, in main

total = load_total(path)

File "report.py", line 7, in load_total

return data["total"]

KeyError: 'total'

Read it like this: the last line says a dictionary lookup failed because there is no key called total. The frame just above it shows the exact line (report.py, line 7, inside load_total). The top frame only shows where that function was called from.

Python also prints chained exceptions. According to the Python tutorial, if a new exception is raised while handling another, you will see "During handling of the above exception, another exception occurred:". If the code deliberately wrapped one error in another (with raise ... from ...), you will see "The above exception was the direct cause of the following exception:". In both cases the first trace printed is the earlier, underlying error, and it is often the one that matters.

JavaScript: read from the top down

In JavaScript, the stack is exposed through the stack property of an error. MDN notes that this property is non-standard and that each engine (V8 in Chrome and Node.js, SpiderMonkey in Firefox, JavaScriptCore in Safari) uses its own format, though the structure is similar: one frame per line, with the most recent call at the top. A sample in V8 style:

TypeError: Cannot read properties of undefined (reading 'name')

at renderUser (app.js:41:22)

at loadPage (app.js:18:5)

at app.js:60:1

The first line gives the type and message. The first "at" line is where it failed: app.js, line 41, column 22, inside renderUser. In Firefox or Safari the same trace may appear as renderUser@app.js:41:22 without the header line, so don't be thrown by the different punctuation.

Modern JavaScript also lets code attach an underlying error with the cause option when it re-throws. MDN describes cause as the "specific original cause of the error". How a console displays it varies, so if a message looks vague, check whether the error object has a cause you can expand.

Java: the first frame, then "Caused by"

Java prints the exception type and message first, then frames starting with the top of the stack, which is the most recent call. A synthetic sample:

java.lang.IllegalStateException: Could not load settings

at com.northgate.App.start(App.java:22)

at com.northgate.App.main(App.java:9)

Caused by: java.io.FileNotFoundException: settings.json (No such file or directory)

at java.base/java.io.FileInputStream.open0(Native Method)

at com.northgate.Config.read(Config.java:15)

... 2 more

The top-level exception says settings could not be loaded. The "Caused by:" section explains why: a file was not found. With long chains, the last "Caused by:" is usually the root cause.

The "... 2 more" line confuses many readers. Oracle's documentation for Throwable.printStackTrace explains that the rest of that trace matches the indicated number of frames at the bottom of the enclosing exception's trace, so Java skips repeating them. Nothing is lost.

Where to look first

  1. Find the exception type and message. In Python, the last line. In JavaScript and Java, the first line. Search the official documentation for that type before anything else.

  2. Find the deepest "Caused by" or the first chained trace. Wrapper errors often say "failed to start" or "request failed"; the underlying one says why.

  3. Find the first frame in your own code. Skip frames from the standard library, frameworks and packages you installed, and look for your project's file or package names. That line is where your code handed over bad input or made a wrong assumption.

  4. Open that file at that line. Read the line and the few lines above it. Ask what value it expected and what it might have received instead.

  5. Check what happened just before. If the trace came from a log, read the lines logged a few seconds earlier. A warning there (a timeout, a missing setting) often explains the crash. On Windows, the same habit applies to reading Event Viewer logs.

Common traps

  • Reading the wrong end. Python's most recent call is at the bottom; JavaScript and Java put it at the top.

  • Blaming the library. The last frame is often inside a framework, but the bug is usually in the call your code made into it.

  • Stopping at the wrapper. "Internal Server Error" or "Could not load settings" is a symptom. Keep reading to the cause.

  • Trusting line numbers in built or minified code. Bundled JavaScript may point to line 1, column 50,000. Use source maps or a development build to get real line numbers.

  • Fixing the first error of many. If a log shows dozens of traces, find the earliest one by time. Later errors are often side effects.

  • Pasting the whole trace without checking it. Traces can include file paths with user names, server names, URLs with tokens or customer data in messages. Remove those before sharing; here is how to redact logs before sharing.

A quick worked check

Take the Python sample above. Type and message: KeyError: 'total'. No chained exception. First frame in your code: report.py, line 7. Likely question: does the file being read actually contain a total field, or is it spelled differently? That is a specific, testable next step, which is the point of reading a trace carefully.

Get a plain-English read of your trace

EasyToDecode is launching soon. It will read the trace or log you paste, quote the lines that matter (the exception, the root cause and the first frame in your code), flag what's missing to diagnose it, and suggest questions to ask or checks to run next. See how it works or join the waitlist to hear when it opens.

Questions

Do I read a stack trace from the top or the bottom?

It depends on the language. Python prints "most recent call last", so start at the bottom. JavaScript engines and Java list the most recent call first, so start at the top.

What does "Caused by" mean in a Java stack trace?

It introduces the underlying exception that the code caught and wrapped in a new one. With several "Caused by" sections, the last one is usually the root cause.

What does "... 3 more" mean in Java?

According to Oracle's Throwable documentation, it means the remaining frames are the same as the bottom frames of the enclosing exception's trace, so they are not repeated.

Why does my JavaScript stack trace look different in Firefox and Chrome?

MDN notes that the stack property is non-standard and each engine uses its own format. The content is similar: one frame per line, most recent call first.

Sources

  1. Python documentation: Errors and Exceptions (tutorial) (checked October 10, 2026)
  2. Python documentation: traceback module (checked October 10, 2026)
  3. MDN Web Docs: Error.prototype.stack (checked October 10, 2026)
  4. MDN Web Docs: Error.prototype.cause (checked October 10, 2026)
  5. Oracle Java SE 21 API: java.lang.Throwable (checked October 10, 2026)

About this guide. Prepared by the EasyToDecode editorial team. Facts were checked against the official sources listed above (last checked October 10, 2026).

How we prepare and check our guides

General information, not legal, financial or tax advice. Rules differ by state, province and territory and change over time; check the sources and, for decisions with legal or financial consequences, a qualified professional.