Skip to content

Commit

Permalink
errors: disp ver on fatal except that causes exit
Browse files Browse the repository at this point in the history
Display Node.js version at the end of stacktraces
on fatal exception that causes exit.
Easier for debugging so you don't have
to ask "what node version are you on?",
it is directly in the error the user
copy/paste from when asking for help.

Fixes: #29731

PR-URL: #38332
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
  • Loading branch information
theoludwig authored and mhdawson committed Sep 8, 2021
1 parent 33b5107 commit 59d3d54
Show file tree
Hide file tree
Showing 57 changed files with 155 additions and 2 deletions.
8 changes: 8 additions & 0 deletions doc/api/cli.md
Expand Up @@ -605,6 +605,13 @@ added: v0.8.0

Silence deprecation warnings.

### `--no-extra-info-on-fatal-exception`
<!-- YAML
added: REPLACEME
-->

Hide extra information on fatal exception that causes exit.

### `--no-force-async-hooks-checks`
<!-- YAML
added: v9.0.0
Expand Down Expand Up @@ -1423,6 +1430,7 @@ Node.js options that are allowed are:
* `--napi-modules`
* `--no-deprecation`
* `--no-experimental-repl-await`
* `--no-extra-info-on-fatal-exception`
* `--no-force-async-hooks-checks`
* `--no-warnings`
* `--node-memory-debug`
Expand Down
3 changes: 3 additions & 0 deletions doc/node.1
Expand Up @@ -273,6 +273,9 @@ It is kept for compatibility.
.It Fl -no-deprecation
Silence deprecation warnings.
.
.It Fl -no-extra-info-on-fatal-exception
Hide extra information on fatal exception that causes exit.
.
.It Fl -no-force-async-hooks-checks
Disable runtime checks for `async_hooks`.
These will still be enabled dynamically when `async_hooks` is enabled.
Expand Down
4 changes: 4 additions & 0 deletions src/node_errors.cc
Expand Up @@ -414,6 +414,10 @@ static void ReportFatalException(Environment* env,
}
}

if (env->options()->extra_info_on_fatal_exception) {
FPrintF(stderr, "\nNode.js %s\n", NODE_VERSION);
}

fflush(stderr);
}

Expand Down
5 changes: 5 additions & 0 deletions src/node_options.cc
Expand Up @@ -511,6 +511,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"show stack traces on process warnings",
&EnvironmentOptions::trace_warnings,
kAllowedInEnvironment);
AddOption("--extra-info-on-fatal-exception",
"hide extra information on fatal exception that causes exit",
&EnvironmentOptions::extra_info_on_fatal_exception,
kAllowedInEnvironment,
true);
AddOption("--unhandled-rejections",
"define unhandled rejections behavior. Options are 'strict' "
"(always raise an error), 'throw' (raise an error unless "
Expand Down
1 change: 1 addition & 0 deletions src/node_options.h
Expand Up @@ -150,6 +150,7 @@ class EnvironmentOptions : public Options {
bool trace_tls = false;
bool trace_uncaught = false;
bool trace_warnings = false;
bool extra_info_on_fatal_exception = true;
std::string unhandled_rejections;
std::string userland_loader;
bool verify_base_objects =
Expand Down
2 changes: 2 additions & 0 deletions test/message/assert_throws_stack.out
Expand Up @@ -32,3 +32,5 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
expected: { bar: true },
operator: 'throws'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/core_line_numbers.out
Expand Up @@ -12,3 +12,5 @@ RangeError: Invalid input
at Function.Module._load (node:internal/modules/cjs/loader:*:*)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:*:*)
at node:internal/main/run_main_module:*:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/error_aggregateTwoErrors.out
Expand Up @@ -11,3 +11,5 @@ AggregateError: original
at node:internal/main/run_main_module:*:* {
code: 'ERR0'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/error_exit.out
Expand Up @@ -20,3 +20,5 @@ AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
expected: 2,
operator: 'strictEqual'
}

Node.js *
Binary file modified test/message/error_with_nul.out
Binary file not shown.
2 changes: 2 additions & 0 deletions test/message/esm_display_syntax_error.out
Expand Up @@ -5,3 +5,5 @@ await async () => 0;
SyntaxError: Unexpected reserved word
at Loader.moduleStrategy (node:internal/modules/esm/translators:*:*)
at async link (node:internal/modules/esm/module_job:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_display_syntax_error_import.out
Expand Up @@ -7,3 +7,5 @@ SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-ex
at async Loader.import (node:internal/modules/esm/loader:*:*)
at async Object.loadESM (node:internal/process/esm_loader:*:*)
at async handleMainPromise (node:internal/modules/run_main:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_display_syntax_error_import_module.out
Expand Up @@ -7,3 +7,5 @@ SyntaxError: The requested module './module-named-exports.mjs' does not provide
at async Loader.import (node:internal/modules/esm/loader:*:*)
at async Object.loadESM (node:internal/process/esm_loader:*:*)
at async handleMainPromise (node:internal/modules/run_main:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_display_syntax_error_module.out
Expand Up @@ -4,3 +4,5 @@ await async () => 0;

SyntaxError: Malformed arrow function parameter list
at Loader.moduleStrategy (node:internal/modules/esm/translators:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_loader_not_found.out
Expand Up @@ -16,3 +16,5 @@ Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist' imported from *
at Object.loadESM (node:internal/process/esm_loader:*:*) {
code: 'ERR_MODULE_NOT_FOUND'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_loader_not_found_cjs_hint_bare.out
Expand Up @@ -14,3 +14,5 @@ Did you mean to import some_module/obj.js?
at link (node:internal/modules/esm/module_job:*:*) {
code: 'ERR_MODULE_NOT_FOUND'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_loader_not_found_cjs_hint_relative.out
Expand Up @@ -18,3 +18,5 @@ Did you mean to import ./test/common/fixtures.js?
at Object.loadESM (node:internal/process/esm_loader:*:*) {
code: 'ERR_MODULE_NOT_FOUND'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/esm_loader_syntax_error.out
Expand Up @@ -7,3 +7,5 @@ await async () => 0;
SyntaxError: Malformed arrow function parameter list
at Loader.moduleStrategy (node:internal/modules/esm/translators:*:*)
at async link (node:internal/modules/esm/module_job:*:*)

Node.js *
12 changes: 12 additions & 0 deletions test/message/eval_messages.out
Expand Up @@ -10,6 +10,8 @@ SyntaxError: Strict mode code may not include a with statement
at [eval]-wrapper:*:*
at evalScript (node:internal/process/execution:*:*)
at node:internal/main/eval_string:*:*

Node.js *
42
42
[eval]:1
Expand All @@ -25,6 +27,8 @@ Error: hello
at evalScript (node:internal/process/execution:*:*)
at node:internal/main/eval_string:*:*

Node.js *

[eval]:1
throw new Error("hello")
^
Expand All @@ -37,6 +41,8 @@ Error: hello
at [eval]-wrapper:*:*
at evalScript (node:internal/process/execution:*:*)
at node:internal/main/eval_string:*:*

Node.js *
100
[eval]:1
var x = 100; y = x;
Expand All @@ -51,15 +57,21 @@ ReferenceError: y is not defined
at evalScript (node:internal/process/execution:*:*)
at node:internal/main/eval_string:*:*

Node.js *

[eval]:1
var ______________________________________________; throw 10
^
10
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *

[eval]:1
var ______________________________________________; throw 10
^
10
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *
done
2 changes: 2 additions & 0 deletions test/message/events_unhandled_error_common_trace.out
Expand Up @@ -18,3 +18,5 @@ Emitted 'error' event at:
at Module._compile (node:internal/modules/cjs/loader:*:*)
[... lines matching original stack trace ...]
at node:internal/main/run_main_module:*:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/events_unhandled_error_nexttick.out
Expand Up @@ -13,3 +13,5 @@ Error
Emitted 'error' event at:
at *events_unhandled_error_nexttick.js:*:*
at processTicksAndRejections (node:internal/process/task_queues:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/events_unhandled_error_sameline.out
Expand Up @@ -15,3 +15,5 @@ Emitted 'error' event at:
at Module._compile (node:internal/modules/cjs/loader:*:*)
[... lines matching original stack trace ...]
at node:internal/main/run_main_module:*:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/events_unhandled_error_subclass.out
Expand Up @@ -15,3 +15,5 @@ Emitted 'error' event on Foo instance at:
at Module._compile (node:internal/modules/cjs/loader:*:*)
[... lines matching original stack trace ...]
at node:internal/main/run_main_module:*:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/if-error-has-good-stack.out
Expand Up @@ -33,3 +33,5 @@ AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error
expected: null,
operator: 'ifError'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/internal_assert.out
Expand Up @@ -16,3 +16,5 @@ Please open an issue with this stack trace at https://github.com/nodejs/node/iss
at * {
code: 'ERR_INTERNAL_ASSERTION'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/internal_assert_fail.out
Expand Up @@ -17,3 +17,5 @@ Please open an issue with this stack trace at https://github.com/nodejs/node/iss
at * {
code: 'ERR_INTERNAL_ASSERTION'
}

Node.js *
2 changes: 2 additions & 0 deletions test/message/nexttick_throw.out
Expand Up @@ -5,3 +5,5 @@
ReferenceError: undefined_reference_error_maker is not defined
at *test*message*nexttick_throw.js:*:*
at processTicksAndRejections (node:internal/process/task_queues:*:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/promise_always_throw_unhandled.out
Expand Up @@ -11,3 +11,5 @@ Error: One
at *
at *
at *

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_disabled_by_api.out
Expand Up @@ -24,3 +24,5 @@ Error: an error!
at Module.load (node:internal/modules/cjs/loader:*)
at Function.Module._load (node:internal/modules/cjs/loader:*)
at Module.require (node:internal/modules/cjs/loader:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_enabled_by_api.out
Expand Up @@ -28,3 +28,5 @@ Error: an error!
at Module.load (node:internal/modules/cjs/loader:*)
at Function.Module._load (node:internal/modules/cjs/loader:*)
at Module.require (node:internal/modules/cjs/loader:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_enclosing_function.out
Expand Up @@ -13,3 +13,5 @@ Error: an error!
at Module.load (node:internal/modules/cjs/loader:*)
at Function.Module._load (node:internal/modules/cjs/loader:*)
at Module.require (node:internal/modules/cjs/loader:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_reference_error_tabs.out
Expand Up @@ -13,3 +13,5 @@ ReferenceError: alert is not defined
at require (node:internal/modules/cjs/helpers:*
at Object.<anonymous> (*source_map_reference_error_tabs.js:*
at Module._compile (node:internal/modules/cjs/loader:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_throw_first_tick.out
Expand Up @@ -13,3 +13,5 @@ Error: an exception
at require (node:internal/modules/cjs/helpers:*)
at Object.<anonymous> (*source_map_throw_first_tick.js:5:1)
at Module._compile (node:internal/modules/cjs/loader:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_throw_icu.out
Expand Up @@ -13,3 +13,5 @@ Error: an error
at require (node:internal/modules/cjs/helpers:*
at Object.<anonymous> (*source_map_throw_icu.js:*
at Module._compile (node:internal/modules/cjs/loader:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/source_map_throw_set_immediate.out
Expand Up @@ -6,3 +6,5 @@ Error: goodbye
at Hello *uglify-throw-original.js:5:9*
at *uglify-throw-original.js:9:3*
at processImmediate (node:internal/timers:*)

Node.js *
2 changes: 2 additions & 0 deletions test/message/stack_overflow.out
Expand Up @@ -4,3 +4,5 @@ JSON.stringify(array);
^

[RangeError: Maximum call stack size exceeded]

Node.js *
12 changes: 12 additions & 0 deletions test/message/stdin_messages.out
Expand Up @@ -14,6 +14,8 @@ SyntaxError: Strict mode code may not include a with statement
at Socket.<anonymous> (node:internal/process/execution:*:*)
at Socket.emit (node:events:*:*)
at endReadableNT (node:internal/streams/readable:*:*)

Node.js *
42
42
[stdin]:1
Expand All @@ -31,6 +33,8 @@ Error: hello
at Socket.<anonymous> (node:internal/process/execution:*:*)
at Socket.emit (node:events:*:*)
at endReadableNT (node:internal/streams/readable:*:*)

Node.js *
[stdin]:1
throw new Error("hello")
^
Expand All @@ -46,6 +50,8 @@ Error: hello
at Socket.<anonymous> (node:internal/process/execution:*:*)
at Socket.emit (node:events:*:*)
at endReadableNT (node:internal/streams/readable:*:*)

Node.js *
100
[stdin]:1
let x = 100; y = x;
Expand All @@ -63,15 +69,21 @@ ReferenceError: y is not defined
at Socket.emit (node:events:*:*)
at endReadableNT (node:internal/streams/readable:*:*)

Node.js *

[stdin]:1
let ______________________________________________; throw 10
^
10
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *

[stdin]:1
let ______________________________________________; throw 10
^
10
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *
done
6 changes: 6 additions & 0 deletions test/message/test-no-extra-info-on-fatal-exception.js
@@ -0,0 +1,6 @@
// Flags: --no-extra-info-on-fatal-exception

'use strict';
require('../common');

throw new Error('foo');
12 changes: 12 additions & 0 deletions test/message/test-no-extra-info-on-fatal-exception.out
@@ -0,0 +1,12 @@
*:6
throw new Error('foo');
^

Error: foo
at Object.<anonymous> (*:6:7)
at Module._compile (node:internal/modules/cjs/loader:*:*)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:*:*)
at Module.load (node:internal/modules/cjs/loader:*:*)
at Function.Module._load (node:internal/modules/cjs/loader:*:*)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:*:*)
at node:internal/main/run_main_module:*:*
2 changes: 2 additions & 0 deletions test/message/throw_custom_error.out
Expand Up @@ -2,3 +2,5 @@
throw ({ name: 'MyCustomError', message: 'This is a custom message' });
^
{ name: 'MyCustomError', message: 'This is a custom message' }

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_error_with_getter_throw.out
Expand Up @@ -4,3 +4,5 @@ throw { // eslint-disable-line no-throw-literal
^
[object Object]
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_error_with_getter_throw_traced.out
Expand Up @@ -11,3 +11,5 @@ Thrown at:
at Module._load (node:internal/modules/cjs/loader:*:*)
at executeUserEntryPoint (node:internal/modules/run_main:*:*)
at node:internal/main/run_main_module:*:*

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_in_line_with_tabs.out
Expand Up @@ -3,3 +3,5 @@ before
throw ({ foo: 'bar' });
^
{ foo: 'bar' }

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_non_error.out
Expand Up @@ -2,3 +2,5 @@
throw ({ foo: 'bar' });
^
{ foo: 'bar' }

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_null.out
Expand Up @@ -4,3 +4,5 @@ throw null;
^
null
(Use `* --trace-uncaught ...` to show where the exception was thrown)

Node.js *
2 changes: 2 additions & 0 deletions test/message/throw_null_traced.out
Expand Up @@ -11,3 +11,5 @@ Thrown at:
at Module._load (node:internal/modules/cjs/loader:*:*)
at executeUserEntryPoint (node:internal/modules/run_main:*:*)
at node:internal/main/run_main_module:*:*

Node.js *

0 comments on commit 59d3d54

Please sign in to comment.