640

Does anyone know how to print a stack trace in Node.js?

whackamadoodle3000
  • 6,684
  • 4
  • 27
  • 44
mike.toString
  • 6,409
  • 2
  • 16
  • 3

12 Answers12

744

Any Error object has a stack member that traps the point at which it was constructed.

var stack = new Error().stack
console.log( stack )

or more simply:

console.trace("Here I am!")
isaacs
  • 16,656
  • 6
  • 41
  • 31
  • 2
    or just `sys.puts(new Error().stack)` (after adding the system module) – sirhc Aug 09 '10 at 04:48
  • 6
    As of now, sys is depricated. It is replaced by `'util'`. – Pindatjuh Apr 14 '11 at 18:15
  • 13
    +1 for also showing `new Error().stack`, which works in cases where you don't want to involve the console. – Evgeniy Berezovsky Jul 31 '12 at 04:19
  • 1
    One advantage of ```trace``` is it shows the current line/context as well which ```stack``` does not. The info is in the error object if you want to manually create that line I guess. – studgeek Aug 30 '12 at 16:54
  • 167
    console.log(err.stack) and console.trace() do not give you same results. Whereas err.stack gives you the stack trace for the err object itself (functioning the way we all normally think of exceptions), console.trace() will print out the call stack at the point where console.trace() is being called. So if you catch some error being thrown by some deeper layer of code, console.trace() will not contain that deeper layer code in the stack trace since that code is no longer on the stack. However, console.log(err.stack) will contain the deeper layers as long as it threw an Error object. – d512 Feb 21 '13 at 18:10
246

Now there's a dedicated function on console for that:

console.trace()
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
Mariusz Nowak
  • 32,050
  • 5
  • 35
  • 37
145

As already answered, you can simply use the trace command:

console.trace("I am here");

However, if you came to this question searching about how to log the stack trace of an exception, you can simply log the Exception object.

try {  
  // if something unexpected
  throw new Error("Something unexpected has occurred.");     

} catch (e) {
  console.error(e);
}

It will log:

Error: Something unexpected has occurred.
    at main (c:\Users\Me\Documents\MyApp\app.js:9:15)
    at Object. (c:\Users\Me\Documents\MyApp\app.js:17:1)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3


If your Node.js version is < than 6.0.0, logging the Exception object will not be enough. In this case, it will print only:

[Error: Something unexpected has occurred.]

For Node version < 6, use console.error(e.stack) instead of console.error(e) to print the error message plus the full stack, like the current Node version does.


Note: if the exception is created as a string like throw "myException", it's not possible to retrieve the stack trace and logging e.stack yields undefined.

To be safe, you can use

console.error(e.stack || e);

and it will work for old and new Node.js versions.

Nate Anderson
  • 18,334
  • 18
  • 100
  • 135
Zanon
  • 29,231
  • 20
  • 113
  • 126
  • Won't `console.error(e)` print *everything* in the `e` object, including `e.stack`? – drmrbrewer Mar 01 '17 at 09:02
  • 1
    @drmrbrewer, thank you for pointing this out. It seems that behavior has changed between Node versions 4.x and 7.x (probably a V8 change). I've updated my answer. – Zanon Mar 01 '17 at 16:57
  • 1
    @drmrbrewer confirmed that this behavior changed on version 6.0.0 – Zanon Mar 01 '17 at 17:25
  • do you have a reference for this apparent change in behaviour? I'm still seeing (with node `6.9.4`) that `console.error(e)` only prints the brief message. And I suspect that it's because it prints a `toString` representation of `e`, and `toString` for `e` only returns the message and nothing else: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/toString – drmrbrewer Mar 02 '17 at 14:40
  • @drmrbrewer try installing **[n](https://github.com/tj/n)** to test different Node versions in your machine or see [this test with Node 7.4](https://repl.it/GE5e/1) and compare it with [Node 0.8](http://www.node-console.com/script/code). I could not get a permalink for the last one, but run `console.error(new Error("test"))` to see the difference. Regarding a reference about this change in behavior, I couldn't get one in Node change logs. It seems to be a V8 change, but I also couldn't confirm. – Zanon Mar 02 '17 at 15:47
  • 4
    sorry I just discovered something crucial. See my comment against the related post: http://stackoverflow.com/questions/42528677/how-to-console-log-an-error-in-node-js/42538065#comment72263214_42532877. It seems that logging the error on its own does indeed show the whole content of the error, but trying to concatenate it (like a string) with other text will cause only the brief message part to be used. It all makes a lot more sense with that realisation. – drmrbrewer Mar 02 '17 at 19:52
41

To print stacktrace of Error in console in more readable way:

console.log(ex, ex.stack.split("\n"));

Example result:

[Error] [ 'Error',
  '    at repl:1:7',
  '    at REPLServer.self.eval (repl.js:110:21)',
  '    at Interface.<anonymous> (repl.js:239:12)',
  '    at Interface.EventEmitter.emit (events.js:95:17)',
  '    at Interface._onLine (readline.js:202:10)',
  '    at Interface._line (readline.js:531:8)',
  '    at Interface._ttyWrite (readline.js:760:14)',
  '    at ReadStream.onkeypress (readline.js:99:10)',
  '    at ReadStream.EventEmitter.emit (events.js:98:17)',
  '    at emitKey (readline.js:1095:12)' ]
Zanon
  • 29,231
  • 20
  • 113
  • 126
ruX
  • 7,224
  • 3
  • 39
  • 33
12

@isaacs answer is correct, but if you need more specific or cleaner error stack, you can use this function:

function getCleanerStack() {
   var err = new Error();
   Error.captureStackTrace(err, getCleanerStack);
    
   return err.stack;
}

This function is inspired directly from the console.trace function in NodeJS.

Source code: Recent version or Old version.

Philipp Kyeck
  • 18,402
  • 15
  • 86
  • 123
8

In v15.12.0, there are various methods for doing this,

1. console.trace(anything)
2. Error.captureStackTrace(Object)
3. console.log(new Error().stack)
4. Try Catch - Use console.log(e), where `e` is catched by catch block

OR even better use stacktracejs in any Javascript code

5

Try Error.captureStackTrace(targetObject[, constructorOpt]).

const myObj = {};
function c() {
  // pass
}

function b() {
    Error.captureStackTrace(myObj)
    c()
} 

function a() {
    b()
}

a()

console.log(myObj.stack)

The function a and b are captured in error stack and stored in myObj.

Zheeeng
  • 642
  • 10
  • 21
  • 3
    If you want an error to have a `stack` property, you'll need to call this if Node >= 6: `Error.captureStackTrace(error)`. – cjbarth Aug 27 '18 at 16:17
  • Note that if you don't want the frame who called `Error.captureStackTrace` to show up in the stack trace, you can omit it by passing it as the `constructorOpt` arg. – Cabrera Jan 05 '19 at 19:51
3

In case someone is still looking for this like I was, then there is a module we can use called "stack-trace". It is really popular. NPM Link

Then walk through the trace.

  var stackTrace = require('stack-trace');
  .
  .
  .
  var trace = stackTrace.get();
  trace.map(function (item){ 
    console.log(new Date().toUTCString() + ' : ' +  item.toString() );  
  });

Or just simply print the trace:

var stackTrace = require('stack-trace');
.
.
.
var trace = stackTrace.get();
trace.toString();
Laszlo
  • 61
  • 8
3

Get function caller details:

/**
 * @typedef {Object} TCallerInfo
 * @property {() => string} toString
 * @property {string} str Caller error stack line.
 * @property {string} file Caller file path.
 * @property {number} line Caller line.
 * @property {number} col Caller column.
 * @property {Error} error Caller error stack instance.
 */

/**
 * @returns {TCallerInfo | null}
 */
function getCallerLine() {
  const err = new Error();
  const stack = err.stack || '';
  const callerLine = stack.split(/\n\s*at\s+/g);

  if (callerLine.length >= 2) {
    const str = callerLine[3];
    const [file, line, col] = str
      .replace(/^\s*at\s+/, '')
      .replace(/^(.*):(\d+):(\d+)$/, '$1|$2|$3')
      .split(/\|/g);

    const o = {
      toString: () => str,

      get str() {
        return str;
      },

      get file() {
        return file;
      },

      get line() {
        return parseInt(line);
      },

      get col() {
        return parseInt(col);
      },

      get error() {
        return err;
      },
    };

    return o;
  } else {
    return null;
  }
}

Usage:

function foo() {
  console.info(getCallerLine());
}

foo(); // Prints this line as Caller Line details.
Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
3

For what I know printing the complete stack trace in nodejs is not possible, you can just print a "partial" stack trace, you can not see from where you came from in the code, just where the Exception occur. That's what Ryan Dahl explains in this youtube video. http://youtu.be/jo_B4LTHi3I at min 56:30 for being precise. Hope this helps

ElHacker
  • 1,687
  • 17
  • 18
2

If you want to only log the stack trace of the error (and not the error message) Node 6 and above automatically includes the error name and message inside the stack trace, which is a bit annoying if you want to do some custom error handling:

console.log(error.stack.replace(error.message, ''))

This workaround will log only the error name and stack trace (so you can, for example, format the error message and display it how you want somewhere else in your code).

The above example would print only the error name follow by the stack trace, for example:

Error: 
    at /Users/cfisher/Git/squashed/execProcess.js:6:17
    at ChildProcess.exithandler (child_process.js:213:5)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:877:16)
    at Socket.<anonymous> (internal/child_process.js:334:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:498:12)

Instead of:

Error: Error: Command failed: sh ./commands/getBranchCommitCount.sh HEAD
git: 'rev-lists' is not a git command. See 'git --help'.

Did you mean this?
        rev-list

    at /Users/cfisher/Git/squashed/execProcess.js:6:17
    at ChildProcess.exithandler (child_process.js:213:5)
    at emitTwo (events.js:106:13)
    at ChildProcess.emit (events.js:191:7)
    at maybeClose (internal/child_process.js:877:16)
    at Socket.<anonymous> (internal/child_process.js:334:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at Pipe._handle.close [as _onclose] (net.js:498:12)
GrayedFox
  • 2,350
  • 26
  • 44
1

you can use node-stack-trace module which is a power full module to track call stacks.

Nitin9791
  • 1,124
  • 1
  • 14
  • 17