blakeembrey / make-error-cause

Make your own nested errors
Other
67 stars 7 forks source link

Use in Chrome dev tools doesn't show full stacks #38

Open garyo opened 4 years ago

garyo commented 4 years ago

I've been using make-error-cause in my back end and it works great. Tried it today in my front end, but console.error(err) mangles the stack traces for the causes (because Chrome dev tools doesn't show newlines perhaps?)

image

I also tried console.error(fullStack(err)) and that has the separator text, but omits the stacks entirely (except console.error itself shows the stack of the last, outermost, error when twirled open): image

Is there anything I can do to get nice stack traces for the earlier/inner errors in dev tools?

blakeembrey commented 4 years ago

Thanks for the flag. I expected fullStack to solve the use-case, but to be honest I've never really tested this module in the browser. Should be easy enough to fix by moving to reading error.stack explicitly in fullStack.

blakeembrey commented 4 years ago

Ah, I think this is partially related to https://github.com/blakeembrey/make-error-cause/issues/34. Give me a little more time to figure this out, but feel free to create a PR if you know how to support both correctly.

garyo commented 4 years ago

I don't know if you'll like it, but the following looks good for me in Chrome dev tools and Firefox. Rather than returning a long string, which Chrome mangles (it turns newlines into visible "↵" chars), I just made a version that calls console.log multiple times, with red styling. (Using console.error() is wrong, btw, because that includes its own stack trace -- but it's the stack at the point of calling console.error(), which is useless.) I also added a console group to keep them together nicely.

Maybe you could include this as an alternative way of printing error chains, in browser environment.

function logError(error: Error | BaseError) {
  const SEPARATOR_TEXT = '--- which was caused by the following: ---'
  const chain: Error[] = [];
  let cause: Error | undefined = error;

  while (cause) {
    chain.push(cause);
    cause = (cause as BaseError).cause;
  }

  if (chain.length > 1)
    console.group('Error:')
  chain.forEach((err, idx) => {
    console.log(`%c${err.stack}`, 'color:red')
    if (idx < chain.length - 1)
      console.log(`%c${SEPARATOR_TEXT}`, 'color:red; font-style:italic')
  })
  if (chain.length > 1)
    console.groupEnd()
}

Here's what it looks like: image

garyo commented 4 years ago

Also just using .map(err => err.stack) in fullStack() works OK too, as you thought it would. It's important not to use inspect though -- either that itself or some result of it causes Chrome dev tools to quote the newlines and mangle the stacks. I'd send a PR but I'm not sure how to change behavior on node vs. browser. Anyway, here's the browser version that's working for me:

function myFullStack(error: Error | BaseError) {
  const chain: Error[] = [];
  let cause: Error | undefined = error;

  while (cause) {
    chain.push(cause);
    cause = (cause as BaseError).cause;
  }

  return chain
    .map(err => inspect(err.stack))
    .join(SEPARATOR_TEXT);
}