Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incompatibility with bluebird long stack traces - thoughts on workarounds? #12

Open
Druotic opened this issue Aug 24, 2017 · 4 comments

Comments

@Druotic
Copy link

Druotic commented Aug 24, 2017

When enabling bluebird's long stack traces, the appended Caused By... gets removed and a confusing/misleading stacktrace is created. The resulting stacktrace is the first part of the nested error stacktrace plus the first few lines of the Caused By: stacktrace appended with no indication of start/stop of stacktraces (plus the From previous event: trace after). Likewise, if the error has been nested multiple times, all of the nested (Caused By:) stacks get chopped/appending to the first stack.

https://github.com/petkaantonov/bluebird/blob/fdd44ee3af6d4fc2570a0f877ca82805a477c6b8/src/debuggability.js#L554 is to blame. I was considering adding a bluebird option to opt out of it, but was curious if this was something you had encountered and worked around previously. The regex being used is /^\s*at\s*/, so prepending at i.e. at Caused by: ... is another possible workaround.

let Promise = require('bluebird')
const NestedError = require('nested-error-stacks')

const throwError = () => { return Promise.reject(new Error('some error')) }

;(async function () {

  await throwError()
  .catch(err => {
    throw new NestedError('nested', err)
  }).catch (err => console.log(`BLUEBIRD_DEBUG not set: ${err.stack}\n`))

  process.env.BLUEBIRD_DEBUG = 1
  delete require.cache[require.resolve('bluebird')]
  Promise = require('bluebird')

  await throwError()
  .catch(err => {
    throw new NestedError('nested', err)
  }).catch(err => console.log(`BLUEBIRD_DEBUG=1: ${err.stack}\n`))

})()

/*
BLUEBIRD_DEBUG not set: NestedError: nested
    at throwError.catch.err (/Users/james.beavers/repos/test/bluebirdStacks.js:10:11)
    at tryCatcher (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromiseCtx (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:606:10)
    at Async._drainQueue (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:138:12)
    at Async._drainQueues (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:733:5)
Caused By: Error: some error
    at throwError (/Users/james.beavers/repos/test/bluebirdStacks.js:4:50)
    at /Users/james.beavers/repos/test/bluebirdStacks.js:8:9
    at Object.<anonymous> (/Users/james.beavers/repos/test/bluebirdStacks.js:22:3)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:575:3

BLUEBIRD_DEBUG=1: NestedError: nested
    at throwError.catch.err (/Users/james.beavers/repos/test/bluebirdStacks.js:19:11)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:733:5)
    at throwError (/Users/james.beavers/repos/test/bluebirdStacks.js:4:50)
    at /Users/james.beavers/repos/test/bluebirdStacks.js:17:9
From previous event:
    at /Users/james.beavers/repos/test/bluebirdStacks.js:18:9
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:169:7)
*/

After changing how stacks are combined: stack += '\nat Caused By: ' + nested.stack;, the result is:

BLUEBIRD_DEBUG not set: NestedError: nested
    at throwError.catch.err (/Users/james.beavers/repos/test/bluebirdStacks.js:10:11)
    at tryCatcher (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromiseCtx (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/promise.js:606:10)
    at Async._drainQueue (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:138:12)
    at Async._drainQueues (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues (/Users/james.beavers/repos/test/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:733:5)
at Caused By: Error: some error
    at throwError (/Users/james.beavers/repos/test/bluebirdStacks.js:4:50)
    at /Users/james.beavers/repos/test/bluebirdStacks.js:8:9
    at Object.<anonymous> (/Users/james.beavers/repos/test/bluebirdStacks.js:22:3)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:575:3

BLUEBIRD_DEBUG=1: NestedError: nested
    at throwError.catch.err (/Users/james.beavers/repos/test/bluebirdStacks.js:19:11)
    at runCallback (timers.js:800:20)
    at tryOnImmediate (timers.js:762:5)
    at processImmediate [as _immediateCallback] (timers.js:733:5)
at Caused By: Error: some error
    at throwError (/Users/james.beavers/repos/test/bluebirdStacks.js:4:50)
    at /Users/james.beavers/repos/test/bluebirdStacks.js:17:9
From previous event:
    at /Users/james.beavers/repos/test/bluebirdStacks.js:18:9
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:169:7)

note: the shorter stacks are due to bluebird automatically trimming common ancestors, internal trace lines, etc, but those lines aren't very useful anyway.

FWIW, this isn't a problem with Q's longStackSupport.

I can open a PR to prepend at, but I assume that would lead to a major version bump and might not be the preferred approach. Getting an opt-out merged into bluebird and released would probably take a while. Do you have a preference @mdlavin, or any other alternative ideas?

@mdlavin
Copy link
Owner

mdlavin commented Aug 26, 2017

What about appending the 'at ' only when BLUEBIRD_DEBUG is set? That would leave the behavior untouched for most people but would still work better when bluebird is used?

I haven't seen this problem, but I also have stopped using Bluebird/Q since the newer versions of node have async/await support.

Druotic added a commit to Druotic/nested-error-stacks that referenced this issue Aug 26, 2017
Druotic added a commit to Druotic/nested-error-stacks that referenced this issue Aug 26, 2017
Druotic added a commit to Druotic/nested-error-stacks that referenced this issue Aug 26, 2017
@Druotic
Copy link
Author

Druotic commented Aug 26, 2017

That'd work for me. Sorry for the spam - forgot to rebase first. Regarding async/await - it still seems like some people might continue to use bluebird along with async/await for the convenience functions that native promises don't support - e.g. timeouts, tap, etc.

Just realized I didn't add any documentation to point out this new behavior if either of the environment variables are set. I'll add a commit in a sec.

Druotic added a commit to Druotic/nested-error-stacks that referenced this issue Aug 26, 2017
Druotic added a commit to Druotic/nested-error-stacks that referenced this issue Aug 26, 2017
@zommerfelds
Copy link

I just hit the same issue. I haven't looked into how either library is implemented, but if you say that Bluebird removes parts of the stack trace, would it be better to fix it on their end?
Regarding the BLUEBIRD_DEBUG variable: we don't set it, but because NODE_ENV is set to development we get the Bluebird long stacktraces too. I just found the variable BLUEBIRD_LONG_STACK_TRACES as well.

@Druotic
Copy link
Author

Druotic commented Sep 8, 2017

@zommerfelds Initially, I looked into fixing the issue on Bluebird's side, but I felt conflicted about what the right approach was. While Bluebird is making some strict assumptions about the stack and doing some manipulation around those assumptions, I don't feel like their assumptions are necessarily bad.

Appending newlines and strings to a stack is probably a bit unusual. Not bad in this case (as they are very helpful), but it certainly doesn't fit the shape of a normal stack that gets generated when an error is created.

I considered adding an option/env variable to bluebird, but then users of nested-error-stacks would have to know about the issue and would have to go out of their way to opt into the option. Not to mention - getting a change into bluebird and/or getting everyone on board with such an option might be difficult since it'd effectively be an option for just this library (or maybe a small handful of others).

I'm open to alternative ideas, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants