winstonjs/winston · warning
winston: exitOnError cannot be true with no rejection handle
Error message
winston: exitOnError cannot be true with no rejection handlers.
What it means
winston's RejectionHandler catches unhandled promise rejections. When there are no rejection-handler transports registered and logger.exitOnError is true, winston warns that exiting on error is impossible because nothing would consume/log the rejection, then overrides doExit to false so the process keeps running.
Source
Thrown at lib/winston/rejection-handler.js:179
* Logs all relevant information around the `err` and exits the current
* process.
* @param {Error} err - Error to handle
* @returns {mixed} - TODO: add return description.
* @private
*/
_unhandledRejection(err) {
const info = this.getAllInfo(err);
const handlers = this._getRejectionHandlers();
// Calculate if we should exit on this error
let doExit =
typeof this.logger.exitOnError === 'function'
? this.logger.exitOnError(err)
: this.logger.exitOnError;
let timeout;
if (!handlers.length && doExit) {
// eslint-disable-next-line no-console
console.warn('winston: exitOnError cannot be true with no rejection handlers.');
// eslint-disable-next-line no-console
console.warn('winston: not exiting process.');
doExit = false;
}
function gracefulExit() {
debug('doExit', doExit);
debug('process._exiting', process._exiting);
if (doExit && !process._exiting) {
// Remark: Currently ignoring any rejections from transports when
// catching unhandled rejections.
if (timeout) {
clearTimeout(timeout);
}
// eslint-disable-next-line no-process-exit
process.exit(1);
}View on GitHub (pinned to ff0b79de85)
Solutions
- Add at least one rejection handler transport: logger.rejections.handle(new winston.transports.File({ filename: 'rejections.log' })).
- Set exitOnError to false (or an appropriate callback) if you intentionally do not want the process to exit on rejections.
- Verify the rejection handler's transports array is populated (console-print logger.rejections) before relying on exit behavior.
Example fix
// before
const logger = winston.createLogger({ exitOnError: true, rejections: true, transports: [] });
// after
const logger = winston.createLogger({
exitOnError: true,
rejections: { handledBy: [new winston.transports.File({ filename: 'rejections.log' })] }
}); Defensive patterns
Strategy: validation
Validate before calling
// Validate rejection transports before relying on exitOnError
if (logger.exitOnError === true && (!logger.rejections || logger.rejections.transports.length === 0)) {
throw new Error('exitOnError=true requires at least one rejection handler transport');
} Prevention
- Always pair exceptions.handle(...) with rejections.handle(...) including at least one transport.
- Add a rejection transport (Console or File) to every logger that sets exitOnError true.
- Test unhandled rejection behavior in staging, not just uncaught exceptions.
When it happens
Trigger: An unhandled promise rejection occurs while logger.exitOnError (or exitOnError callback returns true) but logger.rejections handledBy / the handler has an empty transports list — i.e. rejections are being handled by the handler but no rejection transports were added.
Common situations: Enabling logger.exceptions.handle() but forgetting logger.rejections.handle(transport); misconfiguring a logger where the rejection handler exists (e.g. rejections: true in createLogger) with no transports; assuming exitOnError guarantees process exit on rejections.
Related errors
- winston: not exiting process.
- { colors, emitErrs, formatters, padLevels, rewriters, stripC
- { %s } was removed in winston@3.0.0.
- { %s } was removed in winston@3.0.0. Use a custom winston.fo
- Logger is required to handle exceptions
AI-assisted analysis of winstonjs/winston@ff0b79de85 (2026-08-31).
Data as JSON: /api/errors/b3f85b4b8fd82187.
Report an issue: GitHub.