What does the call stack (stack trace) contain?
1. What the call stack is
The call stack is a data structure in which JavaScript keeps track of which functions are currently running and in what order they were called.
When an error occurs, JS creates a "snapshot" of this stack - the so-called stack trace, which shows exactly where and in what sequence the code that led to the error was called.
2. What the call stack looks like when an error occurs
Consider an example.
function a() {
b();
}
function b() {
c();
}
function c() {
throw new Error("Something went wrong!");
}
try {
a();
} catch (err) {
console.log(err.stack);
}Console output:
Error: Something went wrong!
at c (<anonymous>:8:9)
at b (<anonymous>:4:3)
at a (<anonymous>:1:3)
at <anonymous>:12:33. What a stack trace contains
Each line in stack is one level of a function call
(bottom to top: from where the error occurred to the topmost function that started the chain).
Let's break it down:
Error: Something went wrong! ← error type and message
at c (<anonymous>:8:9) ← function c() raised the error
at b (<anonymous>:4:3) ← c() was called from b()
at a (<anonymous>:1:3) ← b() was called from a()
at <anonymous>:12:3 ← a() was called in the global scopeEach line indicates:
- the function name (
at c,at b,at a) - the file (or
<anonymous>if unnamed) - the line and column number where the call happened
4. Where the stack is stored
When an error object is created (new Error()), it automatically gets a .stack property that contains:
- the error's name (
Error,TypeError, etc.) - the message (
message) - the call trace (stack trace)
Example:
const err = new Error("Network error");
console.log(err.stack);Output:
Error: Network error
at <anonymous>:1:135. Using the stack for error handling
try {
throw new Error("Unexpected error");
} catch (e) {
console.error("Error:", e.message);
console.error("Call stack:\n", e.stack);
}Output:
Error: Unexpected error
Call stack:
Error: Unexpected error
at <anonymous>:2:9
at ...6. Custom errors also have a stack
If you create your own error via class extends Error,
the .stack property will be available on it too.
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
try {
throw new ValidationError("Invalid email");
} catch (e) {
console.log(e.stack);
}Output:
ValidationError: Invalid email
at <anonymous>:8:9
at ...7. The stack for asynchronous errors
Asynchronous calls (via setTimeout, Promise, await)
can "break" the stack, because they run later, in a different iteration of the event loop.
Example:
function a() {
setTimeout(() => {
throw new Error("Error in the timer");
}, 0);
}
a();Output:
Uncaught Error: Error in the timer
at Timeout._onTimeout (<anonymous>:3:11)Only part of the stack is visible here, because the error happened in a different execution context.
Summary
| Element | What it means |
|---|---|
Error.message | The error's text |
Error.name | The error's type (TypeError, ReferenceError, …) |
Error.stack | The full call path leading to the error |
Each at ... | One function in the call chain |
| Order | The top line is the error site, the lines below show who called it |
Practical uses
- Quickly finding where a failure happened in the code;
- Understanding which functions triggered the error;
- Storing the
stack tracein logs (for example, in Sentry, GlitchTip, Logtail); - Building a trace backend to analyze users' errors.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.