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

Explicitly check cause property on Error instances #94

Closed
ghost opened this issue Mar 29, 2022 · 8 comments · Fixed by #105
Closed

Explicitly check cause property on Error instances #94

ghost opened this issue Mar 29, 2022 · 8 comments · Fixed by #105

Comments

@ghost
Copy link

ghost commented Mar 29, 2022

The current error serializer only walks enumerable properties using a for..in loop. The downside to this is that vanilla errors with their cause property set are not enumerable by default. I don't know if it's spec related or just specific to V8's implementation, but it's a bit wonky/unexpected nonetheless.

This means if you have the following code, the cause property won't actually be logged/printed. It will only log the very first/top-level error.

fastify.get('/throw', async (req, res) => {
  throw new Error('first cool error', {
    cause: new Error('second boring error', {
      cause: new Error('third awesome error'),
    }),
  });
});

Here's what node's inspector prints:

Uncaught [Error: first cool error] {
  [cause]: Error: second boring error
      at REPL5:2:12
      at Script.runInThisContext (node:vm:129:12)
      ... 7 lines matching cause stack trace ...
      at REPLServer.[_line] [as _line] (node:internal/readline/interface:879:18) {
    [cause]: Error: third awesome error
        at REPL5:3:14
        at Script.runInThisContext (node:vm:129:12)
        at REPLServer.defaultEval (node:repl:566:29)
        at bound (node:domain:421:15)
        at REPLServer.runBound [as eval] (node:domain:432:12)
        at REPLServer.onLine (node:repl:893:10)
        at REPLServer.emit (node:events:539:35)
        at REPLServer.emit (node:domain:475:12)
        at REPLServer.[_onLine] [as _onLine] (node:internal/readline/interface:418:12)
        at REPLServer.[_line] [as _line] (node:internal/readline/interface:879:18)
  }
}

Would people be open to a PR that explicitly checks for a cause key alongside the existing for..in check? Are there other ways to achieve this? It seems like this would be an expected/sane default, but perhaps there are downsides to doing this or was previously not done intentionally?

Thanks.

@mcollina
Copy link
Member

mcollina commented Mar 29, 2022

Go for it, would you like to send a Pull Request to address this issue? Remember to add unit tests.

@ghost
Copy link
Author

ghost commented Mar 29, 2022

Yeah, I should be able to take a stab at it. I'm slightly confused actually, at first glance, it looks like the cause should be getting included in the message/stack based on https://github.com/pinojs/pino-std-serializers/blob/master/lib/err.js#L56-L57, which uses the error helpers, and since those don't depend on enumerable properties, not sure why they're actually missing all together. With that being said, I only looked through it at a glance, will explore a bit more this week if I can get some time.

@jsumners
Copy link
Member

The first step is to write a failing test.

@hypesystem
Copy link
Contributor

Is there any news on this? Otherwise I might try and do it

@kibertoad
Copy link
Contributor

@hypesystem go for it!

@hypesystem
Copy link
Contributor

Having almost finished writing the code for this, I noticed that .cause is currently serialized in the error message (see #76 and implementation in #78).

I think these two things are ... kind of redundant when they both exist?

Is there a use case for wanting both the error message to be constructed from .cause chains and to include the chain itself in the serialized result?

Personally, I would prefer the serialized result, as it would contain stack traces of the original Errors, but I'd like some input on how to progress here. What are your opinions?

@hypesystem
Copy link
Contributor

I've added a PR on this #105, but pending my previous questions, I'm wondering if we should clean up the message serialization in the same PR.

@voxpelli
Copy link
Contributor

voxpelli commented Jun 13, 2022

Personally, I would prefer the serialized result, as it would contain stack traces of the original Errors

They are also preserved:

_err.stack = stackWithCauses(err)

voxpelli added a commit to voxpelli/pino-std-serializers that referenced this issue Jun 13, 2022
Instead rely on its content being appended to the message and the stack.

This is an alternative fix to pinojs#94, replacing pinojs#105 and pinojs#108 + makes pinojs#109 not needed
mcollina pushed a commit that referenced this issue Jun 13, 2022
…ead (#110)

* Revert "Nested VError causes (#108)"

This reverts commit 5b88f7e.

* Revert "Serialize errors with cause (#105)"

This reverts commit ae83956.

* Never serialize `.cause` when an `Error`

Instead rely on its content being appended to the message and the stack.

This is an alternative fix to #94, replacing #105 and #108 + makes #109 not needed

* Add tests

* Add explainer comment
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

Successfully merging a pull request may close this issue.

5 participants