winstonjs/winston · warning

winston: not exiting process.

Error message

winston: not exiting process.

What it means

Companion warning to the exitOnError message in RejectionHandler._unhandledRejection. Because there were no rejection handler transports, winston forces doExit = false and prints this warning to make clear the process will NOT exit despite exitOnError being true.

Source

Thrown at lib/winston/rejection-handler.js:181

   * @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

  1. Register a rejection transport so rejections are logged and the exit path proceeds: logger.rejections.handle(transport).
  2. If surviving is acceptable, treat this as informational and add your own process.on('unhandledRejection') logging to avoid silent drops.
  3. Explicitly set exitOnError:false to acknowledge the intended behavior and remove confusion.

Example fix

// before
const logger = winston.createLogger({ exitOnError: true });
// (no rejection transports — process survives rejections)
// after
logger.rejections.handle(
  new winston.transports.File({ filename: 'logs/unhandledRejections.log' })
);
Defensive patterns

Strategy: fallback

Validate before calling

// Ensure the process still handles rejections the way you expect
process.on('unhandledRejection', (reason) => {
  console.error('Unhandled rejection after winston no-op:', reason);
});

Try / catch

process.on('unhandledRejection', (reason) => {
  logger.error('unhandled rejection', { reason: String(reason) });
  if (shouldExitOnError) process.exit(1); // own exit policy as fallback
});

Prevention

When it happens

Trigger: An unhandled promise rejection fires when the rejection handler has zero transports and doExit was initially true; after warning 'exitOnError cannot be true with no rejection handlers.', winston prints this second line and continues running.

Common situations: Same as error 22: logger configured with exitOnError true but no rejection transports; operators expecting the process to die on a bad rejection and a supervisor to restart it — the process instead survives with silently dropped rejections.

Related errors


AI-assisted analysis of winstonjs/winston@ff0b79de85 (2026-08-31). Data as JSON: /api/errors/7be2bd4f1ae94c4c. Report an issue: GitHub.