{"record":{"id":"9e8e4604ab1e2909","repo":"winstonjs/winston","slug":"cannot-log-to-file-without-filename-or-stream","errorCode":null,"errorMessage":"Cannot log to file without filename or stream.","messagePattern":"Cannot log to file without filename or stream\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/winston/transports/file.js","lineNumber":73,"sourceCode":"\n    if (options.filename || options.dirname) {\n      throwIf('filename or dirname', 'stream');\n      this._basename = this.filename = options.filename\n        ? path.basename(options.filename)\n        : 'winston.log';\n\n      this.dirname = options.dirname || path.dirname(options.filename);\n      this.options = options.options || { flags: 'a' };\n    } else if (options.stream) {\n      // eslint-disable-next-line no-console\n      console.warn('options.stream will be removed in winston@4. Use winston.transports.Stream');\n      throwIf('stream', 'filename', 'maxsize');\n      this._dest = this._stream.pipe(this._setupStream(options.stream));\n      this.dirname = path.dirname(this._dest.path);\n      // We need to listen for drain events when write() returns false. This\n      // can make node mad at times.\n    } else {\n      throw new Error('Cannot log to file without filename or stream.');\n    }\n\n    this.maxsize = options.maxsize || null;\n    this.rotationFormat = options.rotationFormat || false;\n    this.zippedArchive = options.zippedArchive || false;\n    this.maxFiles = options.maxFiles || null;\n    this.eol = (typeof options.eol === 'string') ? options.eol : os.EOL;\n    this.tailable = options.tailable || false;\n    this.lazy = options.lazy || false;\n\n    // Internal state variables representing the number of files this instance\n    // has created and the current size (in bytes) of the current logfile.\n    this._size = 0;\n    this._pendingSize = 0;\n    this._created = 0;\n    this._drain = false;\n    this._opening = false;\n    this._ending = false;","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/winstonjs/winston/blob/ff0b79de8562bb322c390fbc82fe71c11f373428/lib/winston/transports/file.js#L55-L91","documentation":"The File transport constructor requires a write destination. If neither a valid filename nor a stream option is provided (the final else branch at line 73), there is nothing to write to, so it throws immediately. This is a fail-fast guard against a transport that could never emit logs.","triggerScenarios":"new winston.transports.File({}) or new winston.transports.File({ maxsize: 1024 }) without filename/stream; filename present but falsy (empty string ''), or filename nested under the wrong key after a config refactor.","commonSituations":"Environment-driven config where LOG_FILE is unset/empty so filename ends up undefined; building transports conditionally and falling through to File with no options; typos like filepath instead of filename.","solutions":["Pass a filename: new winston.transports.File({ filename: 'logs/app.log' }).","If logging to an existing stream, pass stream: someWriteStream instead.","Guard dynamic config: only construct the File transport when the filename/env var is a non-empty string.","Check for key typos (filename, not file or filepath) and that the value is non-empty."],"exampleFix":"// before\nconst fileTransport = new winston.transports.File({ filename: process.env.LOG_FILE }); // LOG_FILE unset\n// after\nconst fileTransport = process.env.LOG_FILE\n  ? new winston.transports.File({ filename: process.env.LOG_FILE })\n  : null;","handlingStrategy":"validation","validationCode":"function requireFileTarget(opts = {}) {\n  const hasFilename = typeof opts.filename === 'string' && opts.filename.length > 0;\n  if (!hasFilename && !opts.stream) {\n    throw new TypeError('File transport requires a non-empty filename or a stream');\n  }\n  return opts;\n}","typeGuard":"const hasFileTarget = (o) => (typeof o?.filename === 'string' && o.filename.length > 0) || !!o?.stream;","tryCatchPattern":"try {\n  fileTransport = new winston.transports.File({ filename: process.env.LOG_FILE });\n} catch (err) {\n  if (err.message.includes('without filename or stream')) {\n    console.error('LOG_FILE is not set; skipping file transport');\n    fileTransport = null;\n  } else throw err;\n}","preventionTips":["Check env vars like LOG_FILE at startup and fail loudly if logging config is required.","Only construct the File transport conditionally when a filename exists.","Watch for empty-string filenames — they are falsy and trigger this error."],"tags":["winston","file-transport","missing-option","constructor-validation"],"backgroundTag":"missing-required-option","analyzedSha":"ff0b79de8562bb322c390fbc82fe71c11f373428","analyzedAt":"2026-08-31T13:33:44.585Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}