winstonjs/winston · warning

Callback function no longer supported as of winston@3.0.0

Error message

Callback function no longer supported as of winston@3.0.0

What it means

winston's Profiler.done() warns when its final argument is a function. In winston 2.x you could pass a callback that received the finished profile log; winston 3.0.0 removed callback support across the logging API, so the callback is silently popped and ignored, and this warning is printed.

Source

Thrown at lib/winston/profiler.js:41

    const Logger = require('./logger');
    if (typeof logger !== 'object' || Array.isArray(logger) || !(logger instanceof Logger)) {
      throw new Error('Logger is required for profiling');
    } else {
      this.logger = logger;
      this.start = Date.now();
    }
  }

  /**
   * Ends the current timer (i.e. Profiler) instance and logs the `msg` along
   * with the duration since creation.
   * @returns {mixed} - TODO: add return description.
   * @private
   */
  done(...args) {
    if (typeof args[args.length - 1] === 'function') {
      // eslint-disable-next-line no-console
      console.warn('Callback function no longer supported as of winston@3.0.0');
      args.pop();
    }

    const info = typeof args[args.length - 1] === 'object' ? args.pop() : {};
    info.level = info.level || 'info';
    info.durationMs = (Date.now()) - this.start;

    return this.logger.write(info);
  }
}

module.exports = Profiler;

View on GitHub (pinned to ff0b79de85)

Solutions

  1. Remove the callback argument from done() and rely on the profiler emitting its own info-level log entry.
  2. Attach a transport or listen to the logger 'logging' event to observe the completed profile log instead of using a callback.
  3. Use logger.profile(id) callback form where supported, or log manually with info.durationMs from the emitted meta.

Example fix

// before
const timer = logger.startTimer();
timer.done('message', function (err, level, msg, meta) { ... });
// after
const timer = logger.startTimer();
timer.done('message');
// observe via transports / logger events instead of a callback
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure no function is passed to Profiler.done
function assertNoCallback(args) {
  if (args.length && typeof args[args.length - 1] === 'function') {
    throw new TypeError('Profiler.done no longer accepts a callback (winston >= 3). Remove it.');
  }
}

Type guard

function hasTrailingCallback(args) {
  return args.length > 0 && typeof args[args.length - 1] === 'function';
}

Prevention

When it happens

Trigger: Calling logger.startTimer().done(function(err, level, msg, meta){ ... }) or var profiler = logger.profile('x'); profiler.done(callback) — passing a function as the last argument to done().

Common situations: Migrating winston 2.x profiling code to 3.x; examples from older blog posts showing profile timers with completion callbacks.

Related errors


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