Node.js "uncaughtException" Crashes a CI Process - Exit Code 1
A synchronous error was thrown and nothing caught it. Node prints the stack, runs any uncaughtException handler, and exits non-zero - failing the job. Unlike an unhandled rejection, this is a synchronous throw.
What this error means
A script aborts with a raw stack trace and exits 1, with the error originating from a throw (or a synchronous library call) that no try/catch surrounded. The stack points straight at the throwing line.
/app/src/config.js:8
throw new Error('missing CONFIG_PATH');
^
Error: missing CONFIG_PATH
at loadConfig (/app/src/config.js:8:9)
at Object.<anonymous> (/app/src/index.js:2:16)Common causes
A synchronous throw with no surrounding try/catch
Code threw (a validation error, a failed JSON.parse, a missing env var) on a path that nothing wrapped in try/catch, so it propagated to the top and terminated the process.
An error thrown inside an event/callback
A throw inside a synchronous event handler or callback escapes the call site and becomes an uncaught exception, since there is no caller frame to catch it.
How to fix it
Catch the error where it can be handled
Wrap the fallible operation and handle or rethrow with context. This is the real fix - an uncaught exception is a genuine bug, not a transient failure.
try {
const cfg = loadConfig();
} catch (err) {
console.error('Config load failed:', err.message);
process.exitCode = 1;
}Add a top-level handler for clean shutdown
A last-resort uncaughtException handler lets you log and exit deliberately, but it should not be used to swallow errors and keep running.
process.on('uncaughtException', (err) => {
console.error('Uncaught exception:', err);
process.exit(1);
});How to prevent it
- Wrap fallible synchronous work in
try/catchwith useful context. - Validate inputs/env early so failures are explicit, not stray throws.
- Treat an uncaught exception as a bug to fix, not a flake to retry.