{"record":{"id":"3174f15013b4e3d1","repo":"winstonjs/winston","slug":"callback-function-no-longer-supported-as-of-winsto-3174f1","errorCode":null,"errorMessage":"Callback function no longer supported as of winston@3.0.0","messagePattern":"Callback function no longer supported as of winston@3\\.0\\.0","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/winston/profiler.js","lineNumber":41,"sourceCode":"    const Logger = require('./logger');\n    if (typeof logger !== 'object' || Array.isArray(logger) || !(logger instanceof Logger)) {\n      throw new Error('Logger is required for profiling');\n    } else {\n      this.logger = logger;\n      this.start = Date.now();\n    }\n  }\n\n  /**\n   * Ends the current timer (i.e. Profiler) instance and logs the `msg` along\n   * with the duration since creation.\n   * @returns {mixed} - TODO: add return description.\n   * @private\n   */\n  done(...args) {\n    if (typeof args[args.length - 1] === 'function') {\n      // eslint-disable-next-line no-console\n      console.warn('Callback function no longer supported as of winston@3.0.0');\n      args.pop();\n    }\n\n    const info = typeof args[args.length - 1] === 'object' ? args.pop() : {};\n    info.level = info.level || 'info';\n    info.durationMs = (Date.now()) - this.start;\n\n    return this.logger.write(info);\n  }\n}\n\nmodule.exports = Profiler;\n","sourceCodeStart":23,"sourceCodeEnd":54,"githubUrl":"https://github.com/winstonjs/winston/blob/ff0b79de8562bb322c390fbc82fe71c11f373428/lib/winston/profiler.js#L23-L54","documentation":"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.","triggerScenarios":"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().","commonSituations":"Migrating winston 2.x profiling code to 3.x; examples from older blog posts showing profile timers with completion callbacks.","solutions":["Remove the callback argument from done() and rely on the profiler emitting its own info-level log entry.","Attach a transport or listen to the logger 'logging' event to observe the completed profile log instead of using a callback.","Use logger.profile(id) callback form where supported, or log manually with info.durationMs from the emitted meta."],"exampleFix":"// before\nconst timer = logger.startTimer();\ntimer.done('message', function (err, level, msg, meta) { ... });\n// after\nconst timer = logger.startTimer();\ntimer.done('message');\n// observe via transports / logger events instead of a callback","handlingStrategy":"type-guard","validationCode":"// Ensure no function is passed to Profiler.done\nfunction assertNoCallback(args) {\n  if (args.length && typeof args[args.length - 1] === 'function') {\n    throw new TypeError('Profiler.done no longer accepts a callback (winston >= 3). Remove it.');\n  }\n}","typeGuard":"function hasTrailingCallback(args) {\n  return args.length > 0 && typeof args[args.length - 1] === 'function';\n}","tryCatchPattern":null,"preventionTips":["Do not pass callbacks to any winston 3.x logging/profiling method.","Consume profile results via transports or the logger 'logging' event.","Type your logger wrapper so timer.done() has no callback parameter."],"tags":["deprecation","winston","callbacks","profiling"],"backgroundTag":"callback-api-removed","analyzedSha":"ff0b79de8562bb322c390fbc82fe71c11f373428","analyzedAt":"2026-08-31T13:33:44.585Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}