ChatGPT解决这个技术问题 Extra ChatGPT

How to print a stack trace in Node.js?

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


i
isaacs

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!")

or just sys.puts(new Error().stack) (after adding the system module)
As of now, sys is depricated. It is replaced by 'util'.
+1 for also showing new Error().stack, which works in cases where you don't want to involve the console.
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.
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.
M
Mike Samuel

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

console.trace()

Just make sure to heed the above comment about console.trace().
By default this will only show 10 frames, you can use the command-line argument to increase this, e.g. --stack_trace_limit=200
What if you want to output to a log file?
That doesn't seem to work with promises and async/await, does it?
T
The Red Pea

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.


Won't console.error(e) print everything in the e object, including e.stack?
@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.
@drmrbrewer confirmed that this behavior changed on version 6.0.0
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: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
sorry I just discovered something crucial. See my comment against the related post: stackoverflow.com/questions/42528677/…. 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.
Z
Zanon

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)' ]

S
Squidward Tentacles

@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, getStack);

   return err.stack;
}

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

Source code: Recent version or Old version.


it doesn't work, only show stack from current line (not the line this error occured) . err.stack is more correct answer.
getStack is not defined
Should be getCleanerStack instead of getStack on line 3
佚名

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


Z
Zheeeng

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.


If you want an error to have a stack property, you'll need to call this if Node >= 6: Error.captureStackTrace(error).
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.
E
ElHacker

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


true, but the module in @Timboudreau's answer "fixes" that
L
Laszlo

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();

G
GrayedFox

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)

E
Eduardo Cuomo

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.

N
Nitin9791

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