-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
Error.name should not contain display elements #20253
Comments
(Aside: There's no nodejs/error team. Wonder if there should be.) |
I sometimes find that formatting odd too. I guess the choice is to make the error message look like I am not sure about overriding cc @jasnell |
Also this may create quite a churn if we change the |
As a user I wouldn't see it as "overriding" as the whole But yeah, Node could also choose to only do it for internal errors. I just think users will quickly think "wait, this is very helpful, why can't I have this for all my errors". |
@felixfbecker Well I think it's useful but I would not say all users would agree. It would be better if this is opt-in, since I believe there will be quite a few users depending on the current behavior of |
Wouldn't that argument apply just as well to built-in errors (analyzing errors in logs)? |
@felixfbecker I would say not since our errors are not instances of native errors. They are extended. |
The current behavior is actually spec'd, see https://tc39.github.io/ecma262/#sec-error.prototype.tostring
|
Got it, wasn't aware of that. Frankly in that case I would prefer having no code printed in The code will still show up if logged with > console.error(Object.assign(new Error('test'), { code: 'ERR_THIS_IS_A_TEST' }))
{ Error: test
at repl:1:29
at Script.runInThisContext (vm.js:65:33)
at REPLServer.defaultEval (repl.js:246:29)
at bound (domain.js:375:14)
at REPLServer.runBound [as eval] (domain.js:388:12)
at REPLServer.onLine (repl.js:497:10)
at REPLServer.emit (events.js:132:15)
at REPLServer.emit (domain.js:421:20)
at REPLServer.Interface._onLine (readline.js:285:10)
at REPLServer.Interface._line (readline.js:638:8) code: 'ERR_THIS_IS_A_TEST' }
undefined
> try { require('child_process').execSync('asdkljasd', { encoding: 'utf-8' }) } catch (err) { console.error(err) }
{ Error: Command failed: asdkljasd
/bin/sh: asdkljasd: command not found
at checkExecSyncError (child_process.js:574:11)
at Object.execSync (child_process.js:611:13)
at repl:1:32
at Script.runInThisContext (vm.js:65:33)
at REPLServer.defaultEval (repl.js:246:29)
at bound (domain.js:375:14)
at REPLServer.runBound [as eval] (domain.js:388:12)
at REPLServer.onLine (repl.js:497:10)
at REPLServer.emit (events.js:132:15)
at REPLServer.emit (domain.js:421:20)
status: 127,
signal: null,
output: [ null, '', '/bin/sh: asdkljasd: command not found\n' ],
pid: 56111,
stdout: '',
stderr: '/bin/sh: asdkljasd: command not found\n' } Maybe it would be an improvement to make the default uncaught exception handler use |
@felixfbecker It's not so much that the repl prints I think it would be useful to log other properties out in the repl, since I often find myself catching the error and then |
I wasn't specifically talking about the REPL, just used it as a demonstration. Here is the same with $ node -e "throw Object.assign(new Error('test'), { code: 'ERR_TEST' })"
[eval]:1
throw Object.assign(new Error('test'), { code: 'ERR_TEST' })
^
Error: test
at [eval]:1:21
at Script.runInThisContext (vm.js:65:33)
at Object.runInThisContext (vm.js:199:38)
at Object.<anonymous> ([eval]-wrapper:6:22)
at Module._compile (module.js:662:30)
at evalScript (bootstrap_node.js:522:27)
at startup (bootstrap_node.js:169:9)
at bootstrap_node.js:665:3
✘-1 ~
$ node -e "console.error(Object.assign(new Error('test'), { code: 'ERR_TEST' }))"
{ Error: test
at [eval]:1:29
at Script.runInThisContext (vm.js:65:33)
at Object.runInThisContext (vm.js:199:38)
at Object.<anonymous> ([eval]-wrapper:6:22)
at Module._compile (module.js:662:30)
at evalScript (bootstrap_node.js:522:27)
at startup (bootstrap_node.js:169:9)
at bootstrap_node.js:665:3 code: 'ERR_TEST' } I am proposing this as an alternative solution to the problem "we want to show users the error codes of the node core errors when they are printed", because modifying This solution has the added benefit of also exposing other helpful metadata that errors have plenty of as shown in my previous example (e.g. child_process errors have stderr, exit code, signal...). And the amount of information that is printed can already be easily configured. |
I personally like the idea of logging out other properties of an error in those handlers, but I would not think of this as an alternative to put the code in the results of |
I don't have a problem with Node using an internal errors base class that overrides |
@felixfbecker That is enforced by the JS linter actually. (there are still 100+ C++ errors without |
I just had a look at this and played around how this could be fixed and it turns out to be quite a difficult task at hand. We use Manipulating the stack is not an option because the stack itself is also manipulated throughout the code after creating the error with e.g., I guess the best way to solve this is to just adding the properties that we want to show directly on the error as enumerable properties. That way these properties would always be visible when inspecting them (no matter if in the repl or elsewhere). |
The repl would probably need some extra love but that should be fine. Here an example how it would look like when changing the name and printing
|
I don't understand why - wouldn't it result in the same output that is output right now in v10 with the modified In any case, I think going through |
@felixfbecker const err = new Error('foo')
err.toString = () => console.log('called')
Error.prototype.toString.call(err)
> 'Error: foo'
err == 123
> called
> false |
👍 I am going to look into it. |
This aligns the visualization of an error with no stack traces set to zero just as it is done in case the error has no stack trace. PR-URL: nodejs#20802 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
When inspecting nested objects some times a whitespace was added at the end of a line. This fixes this erroneous space. Besides that the `breakLength` was not followed if a single property was longer than the breakLength. It will now break a single property into the key and value in such cases. PR-URL: nodejs#20802 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
Error stacks and multiline error messages were not correct indented. This is fixed by this patch. PR-URL: nodejs#20802 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
When inspecting errors with extra properties while setting the compact option to false, it will now return: [Error: foo] { at repl:1:5 at Script.runInThisContext (vm.js:89:20) bla: true } Instead of: Error: foo at repl:1:5 at Script.runInThisContext (vm.js:91:20) { bla: true } PR-URL: nodejs#20802 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
This aligns the visualization of an error with no stack traces set to zero just as it is done in case the error has no stack trace. PR-URL: #20802 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
When inspecting nested objects some times a whitespace was added at the end of a line. This fixes this erroneous space. Besides that the `breakLength` was not followed if a single property was longer than the breakLength. It will now break a single property into the key and value in such cases. PR-URL: #20802 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
Error stacks and multiline error messages were not correct indented. This is fixed by this patch. PR-URL: #20802 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
When inspecting errors with extra properties while setting the compact option to false, it will now return: [Error: foo] { at repl:1:5 at Script.runInThisContext (vm.js:89:20) bla: true } Instead of: Error: foo at repl:1:5 at Script.runInThisContext (vm.js:91:20) { bla: true } PR-URL: #20802 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
1) Currently extra properties on an error will be ignored, if thrown. This information will from now on be visible. 2) In case someone threw a non error object it would have resulted in `[object Object]`. Instead, the full object will now be visible. 3) Some cases were not detected properly as error before and "Thrown: " was visible before. That is now fixed. PR-URL: nodejs#22436 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
The stack was removed later on instead of never being attached in the first place. PR-URL: nodejs#22436 Refs: nodejs#20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
I might have found a solution. Trying it out right now. |
I tried it out and my approach works relatively well in most cases but as I feared above not in all cases. Therefore I still see no other way. |
1) Currently extra properties on an error will be ignored, if thrown. This information will from now on be visible. 2) In case someone threw a non error object it would have resulted in `[object Object]`. Instead, the full object will now be visible. 3) Some cases were not detected properly as error before and "Thrown: " was visible before. That is now fixed. PR-URL: #22436 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
The stack was removed later on instead of never being attached in the first place. PR-URL: #22436 Refs: #20253 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
what's the current status on this? Will this be a semver major or no? |
@jasnell there was no PR that changed the behavior. And I am not sure how we can address this properly. The only working way for me was to set the name in the constructor, access the stack trace (so it generates the one with the code) and reset the name to the proper one without code. This works relatively well. However, in case the application exits due to the error the stack is generated again (seems like C++ code does that). Therefore the error code is not visible in those cases anymore. If someone knows how to prevent the stack trace from being generated again, we could try this workaround. |
Why do we have to keep the error code in |
Also, formatting This was brought up in #11299 @jasnell
But WPT does not use (So..maybe #11299 should be reopened?) |
I would also prefer to have a "clean" name property instead of adding the code to it but it's not a strong opinion. |
If we want to move the code from (Also, we can use help from the upcoming code-and-learn to fix the |
Do we know what we'd want it replaced with? Checking |
@Trott |
I can live with that. Ideally, I would prefer to avoid the magic/special EDIT: Although I'm sure we can figure out some way to tell |
I'm strongly -1 on moving the code to What I do think is a viable approach long term is to make a proposal to TC-39 to add |
I'm going to take this issue off the 11.0.0 milestone as it would require (a) having a PR, (b) having consensus on the approach, and (c) having TSC sign off to get pulled in to 11 at this point. |
If we still cannot move It's hard to imagine that someone would rely on const match = err.name.match(/(\w+) \[(.+)\]/);
//or
const match = err.stack.match(/(\w+) \[(.+)\]:/);
const [ _, name, code] = match; instead of const {name, code} = err; ? |
@jasnell IIUC, you might be talking about places like const match = err.message.match(someRe);
// expects there is no `[ERR_CODE]` suddenly showing up at the start ? But I believe for errors like those we don't even touch the |
When using `Errors.captureStackFrames` the error's stack property is set again. This adds a helper function that wraps this functionality in a simple API that does not only set the stack including the `code` property but it also improves the performance to create the error. The helper works for thrown errors and errors returned from wrapped functions in case they are Node.js core errors. PR-URL: nodejs#26738 Fixes: nodejs#26669 Fixes: nodejs#20253 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
This is a first step to align the n-api errors towards errors created in JS. The stack still has to be updated to add the error code. PR-URL: nodejs#26738 Fixes: nodejs#26669 Fixes: nodejs#20253 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Joyee Cheung <[email protected]>
Remainder of this is a comment by @felixfbecker in #13937 (comment) that I think deserves its own issue:
I agree that adding the code to the
name
is weird. For mename
is a programmatically-inspectable property, just likecode
, and not for "human consumption" likemessage
. Having pretty formatting in there with a space and brackets goes against that.Browser errors have no
code
property, they always usename
, so that's where this intuition is coming from. For example, forfetch
you would have to check iferr.name === 'AbortError'
. The only other option is usinginstanceof
, but that is bad practice (assert on interfaces, not implementations).Personally I see
code
as a subcategory ofname
, e.g.name
can beTypeError
andcode
ERR_SOCKET_BAD_TYPE
. It's both useful to be able to make assertions about the broader category of and error as well as the exact error reason. For example, in an Express error handler, I might want to never return anyTypeError
s to the client because they are programming errors. Or take p-retry as an example (emphasis mine):Checking
code
here wouldn't be helpful.I would prefer if both
name
andcode
are for programmatic inspection without fancy formatting, andError.prototype.toString()
could be modified to include botherror.name
anderror.code
in the output, astoString()
is unarguably purely for human consumption. Doing this for all errors, including user errors, would be a great feature and encourage users to make use of error codes too. Alternatively it could only be an internal base error class.The text was updated successfully, but these errors were encountered: