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

logger.profile(id, ...args) in winston v3 logs a duration message itself and no longer accepts a completion callback. For backwards compatibility, if the second-to-last argument is a function, winston warns 'Callback function no longer supported as of winston@3.0.0', pops it off the args, and continues without invoking it. This is a migration warning, not a thrown error.

Source

Thrown at lib/winston/logger.js:589

  }

  /**
   * Tracks the time inbetween subsequent calls to this method with the same
   * `id` parameter. The second call to this method will log the difference in
   * milliseconds along with the message.
   * @param {string} id Unique id of the profiler
   * @returns {Logger} - TODO: add return description.
   */
  profile(id, ...args) {
    const time = Date.now();
    if (this.profilers[id]) {
      const timeEnd = this.profilers[id];
      delete this.profilers[id];

      // Attempt to be kind to users if they are still using older APIs.
      if (typeof args[args.length - 2] === 'function') {
        // eslint-disable-next-line no-console
        console.warn(
          'Callback function no longer supported as of winston@3.0.0'
        );
        args.pop();
      }

      // Set the duration property of the metadata
      const info = typeof args[args.length - 1] === 'object' ? args.pop() : {};
      info.level = info.level || 'info';
      info.durationMs = time - timeEnd;
      info.message = info.message || id;
      return this.write(info);
    }

    this.profilers[id] = time;
    return this;
  }

  /**

View on GitHub (pinned to ff0b79de85)

Solutions

  1. Remove the callback; winston v3 profile() emits the completion log event itself — listen via logger.on('logging') or a profile callback-free flow.
  2. Use explicit timing instead: const start = Date.now(); ...; logger.info('msg', { durationMs: Date.now() - start }).
  3. If you need programmatic completion, use logger.startTimer() / profiler.done(info) API of winston v3.

Example fix

// before
logger.profile('db-query', (err, level, msg, meta) => { console.log('done'); });
// after
logger.profile('db-query'); // completion logged automatically on profiler.done
// or
const profiler = logger.startTimer();
profiler.done({ message: 'db-query finished' });
Defensive patterns

Strategy: try-catch

Validate before calling

function safeProfile(logger, id, ...args) {
  const filtered = args.filter(a => typeof a !== 'function');
  return logger.profile(id, ...filtered);
}

Type guard

const usesLegacyProfileCallback = (...args) => typeof args[args.length - 2] === 'function';

Prevention

When it happens

Trigger: Calling logger.profile('id', callback) or logger.profile('id', info, callback) — any profile() call whose args[len-2] is a function, i.e. winston v2-style profiling code run on winston v3+.

Common situations: Upgrading from winston 2.x to 3.x and keeping old profiler code that relied on the callback to time operations; copy-pasted legacy timing helpers.

Related errors


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