winston
>=3.0.0 <4.0.0postconditions11functions9last verified2026-06-24coverage score89%Postconditions: what we check
- createLogger · missing-error-listenerwarningWhencreateLogger() called without .on('error', handler) registered on the returned logger instanceReturnslogger instance that silently swallows transport errors without error listenerRequired handlingCaller MUST attach an 'error' event listener to the logger instance immediately after createLogger(). Without it, transport failures (file system full, permission denied, network transport errors) are silently lost and logs may be dropped. Use: logger.on('error', (err) => { ... }). Source: Winston README — "the logger also emits an 'error' event if an error occurs within the logger itself which you should handle or suppress"costmediumin prodsilent failureusers seedegraded performancevisibilitysilent
- query · query-unhandled-callback-errorerrorWhenlogger.query() callback receives err as first argument when any transport query fails (e.g. File transport ENOENT/EACCES on log read, or transport does not support query method). Callers that omit the err check silently receive null/undefined results.Required handlingCaller MUST check the first argument to the callback: if (err) { handle or rethrow }. Ignoring err causes silent failures in log monitoring dashboards and audit UIs.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[3]
- transports.File · file-transport-missing-per-transport-error-listenerwarningWhennew transports.File() created without transport.on('error', handler). Filesystem errors (ENOSPC disk full, EACCES permission denied, ENOENT missing directory) during log writes are emitted on the transport instance itself — NOT on the parent logger. A logger.on('error') listener does not catch transport-level errors.Required handlingAfter creating a File transport, attach: transport.on('error', (err) => { ... }). This is separate from and required in addition to logger.on('error'). Without it, log file write failures are silently lost and logs are dropped without any alert.costmediumin prodsilent failureusers seedegraded performancevisibilitysilent
- transports.File · file-transport-constructor-throws-on-invalid-optionserrorWhennew transports.File() called with both 'stream' and 'filename'/'dirname' options simultaneously, or with neither a filename nor a stream. Constructor throws synchronously. When File transports are created dynamically (per-tenant log files, runtime-configured paths), uncaught throws crash the request handler.Throws
Error (synchronous, at construction time)Required handlingWrap dynamic new transports.File() calls in try/catch when filename is derived from runtime input. Validate that mutually exclusive options are not passed together.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - transports.Http · http-transport-warn-not-error-on-failurewarningWhentransports.Http used without a 'warn' event listener. HTTP 4xx/5xx responses and connection errors trigger this.emit('warn', err) on the transport — not 'error'. Code that only attaches transport.on('error', handler) silently misses all network transport failures.Required handlingWhen using Http transport and log delivery reliability matters, attach both: transport.on('error', handler) AND transport.on('warn', handler). The 'warn' event carries network failures, not 'error'. Omitting the warn listener means silent log loss to remote aggregators.costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[5]
- configure · configure-throws-on-v2-optionserrorWhenlogger.configure() or createLogger() called with any of the removed winston@2 options: colors, emitErrs, formatters, padLevels, rewriters, stripColors. Throws synchronously with "{ colors, emitErrs, formatters, padLevels, rewriters, stripColors } were removed in winston@3.0.0." Migration codebases frequently pass both old and new options.Throws
Error — deprecated option keys present in configure options objectRequired handlingRemove all deprecated v2 option keys before passing to createLogger() or configure(). Use winston.format.* combinators instead of the removed formatters/padLevels/stripColors options. Wrap logger initialization in try/catch when config is loaded from external sources (env vars, config files) that may contain v2-era options.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - add · add-throws-on-non-objectmode-transporterrorWhenlogger.add() called with a transport that lacks _writableState.objectMode. Throws synchronously with "Transports must WritableStreams in objectMode." Typically surfaces when using third-party custom transports written for winston@2 (non-stream transports) not yet updated for @3.Throws
Error — transport is not a WritableStream in objectModeRequired handlingWrap logger.add() in try/catch when transport type is not known at compile time. Verify third-party transports extend winston-transport (which sets objectMode: true) before dynamically adding them. For per-request transport patterns, validate transport instance before calling add().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - cli · cli-throws-unconditionallyerrorWhenlogger.cli() called on any logger instance in winston@3+. Throws synchronously with "Logger.cli() was removed in winston@3.0.0\nUse a custom winston.formats.cli() instead." This is a hard migration trap — winston@2 codebases that call logger.cli() crash at startup after upgrade.Throws
Error — Logger.cli() was removed in winston@3.0.0Required handlingRemove all logger.cli() calls when upgrading from winston@2 to @3. Replace with winston.format.cli() composed into the logger's format chain: createLogger({ format: winston.format.cli(), transports: [...] }). If logger.cli() is called at startup, the synchronous throw will crash the process before any error handler can attach. Audit migration paths carefully.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - exceptions.handle · exceptions-handle-installs-process-exitwarningWhenlogger.exceptions.handle(transport) or createLogger({ exceptionHandlers: [...] }) registers a `process.on('uncaughtException', ...)` listener. When an uncaught exception fires, the handler logs to the registered transports AND calls process.exit(1) after a 3-second timeout (when logger.exitOnError is true, the default). Code that relies on a long-running process being kept alive after the log is written will be terminated.Required handlingTo prevent process termination on uncaught exception while still logging, set `exitOnError: false` on the logger options OR pass a function: `exitOnError: (err) => false`. For services where reliability matters, prefer setting up domain-specific error boundaries (express error middleware, async-context try/catch, AbortController) rather than relying on winston's exception handler as a safety net — winston exits the process regardless of whether the log write succeeded.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
- exceptions.handle · exception-handler-constructor-requires-loggererrorWhennew winston.ExceptionHandler() called without a logger argument. Throws synchronously with "Logger is required to handle exceptions". Encountered when users build a standalone ExceptionHandler outside the auto-created `logger.exceptions` path (e.g. shared exception capture across multiple loggers).Throws
Error — Logger is required to handle exceptionsRequired handlingAlways pass a valid Logger instance to `new winston.ExceptionHandler(logger)`. The idiomatic path is to use the auto-created `logger.exceptions` accessor and call `.handle(...transports)` on it — that path is guaranteed to have a logger bound. Avoid manual ExceptionHandler construction unless you have a specific multi-logger coordination requirement.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - rejections.handle · rejections-handle-installs-process-exitwarningWhenlogger.rejections.handle(transport) or createLogger({ rejectionHandlers: [...] }) registers a `process.on('unhandledRejection', ...)` listener. On unhandled rejection, the handler logs to the registered transports and calls process.exit(1) after a 3-second timeout when `exitOnError` is true (default). Combined with Node 15+'s default `throw` mode on unhandled rejections, this means promises that lose their .catch() WILL terminate the service — even if the promise itself was fire-and-forget.Required handlingTreat unhandled rejection capture as a last-resort observability tool, not a safety net. Every async function MUST have explicit error handling at the awaiter / .catch(). If you set `rejectionHandlers` to capture telemetry, set `exitOnError: false` to avoid terminating long-lived services on a single stray promise. For Express/Koa/Nest stacks, rely on framework-provided async error middleware and use `rejections.handle()` only to capture the log of last resort.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisible
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
- [1]github.com/winstonjs/winstonwinstonjs/winston
- [2]github.com/winstonjs/winston/blobwinstonjs/winston · README.md
- [3]github.com/winstonjs/winston/blobwinstonjs/winston · logger.js
- [4]github.com/winstonjs/winston/blobwinstonjs/winston · file.js
- [5]github.com/winstonjs/winston/blobwinstonjs/winston · http.js
- [6]github.com/winstonjs/winston/blobwinstonjs/winston · UPGRADE-3.0.md
- [7]github.com/winstonjs/winston/blobwinstonjs/winston · exception-handler.js
- [8]github.com/winstonjs/winstonwinstonjs/winston
- [9]github.com/winstonjs/winston/blobwinstonjs/winston · rejection-handler.js
- [10]github.com/winstonjs/winstonwinstonjs/winston
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: winston
Package: winston
Version: 3.x
Category: logging (Logging library)
Status: ✅ Complete
Official Documentation
- Main Docs: https://github.com/winstonjs/winston#readme
- Transports: https://github.com/winstonjs/winston#transports
- Exceptions: https://github.com/winstonjs/winston#handling-uncaught-exceptions-with-winston
- Awaiting Logs: https://github.com/winstonjs/winston#awaiting-logs-to-be-written-in-winston
- npm: https://www.npmjs.com/package/winston
Behavioral Requirements
Transport Errors: File write failures, network issues Should add error event listeners to logger and transports Transport failures should not crash application handleExceptions option can mask errors if not configured properly
Contract Rationale
Logger errors are silent by default: Transport failures go unnoticed File transports can fail: Disk full, permissions, path issues Network transports can fail: Connection issues, timeouts handleExceptions requires careful configuration: Can prevent proper error handling
Real-World Evidence (2026-04-02)
- santiq/bulletproof-nodejs (⭐5k): createLogger without .on('error') — TP violation
- getmaxun/maxun (⭐15k): createLogger with File transports, no .on('error') — TP violation
- whyour/qinglong (⭐19k): createLogger with .on('error') — correct, no violation
- 2/4 repos scanned have the antipattern = 50% prevalence in real world
Created: 2026-02-26 Updated: 2026-04-02 Status: ✅ COMPLETE (evidence_quality upgraded from stub to confirmed)