denoland/deno · error · TypeError
ERR_CONSOLE_WRITABLE_STREAM
ERR_CONSOLE_WRITABLE_STREAM
Error message
Console expects a writable stream instance for stdout
What it means
The Node-compatible Console class (require('node:console').Console, the options-object constructor) builds a console around streams you supply. options.stdout must be a writable stream - an object with a .write function. ERR_CONSOLE_WRITABLE_STREAM is thrown at construction when stdout is missing or lacks .write. Console accepts only Node-style streams, never file paths or WHATWG web streams.
Source
Thrown at ext/node/polyfills/internal/console/constructor.mjs:156
if (!options || typeof options.write === "function") {
options = {
stdout: options,
stderr: arguments[1],
ignoreErrors: arguments[2],
};
}
const {
stdout,
stderr = stdout,
ignoreErrors = true,
colorMode = "auto",
inspectOptions,
groupIndentation,
} = options;
if (!stdout || typeof stdout.write !== "function") {
throw new ERR_CONSOLE_WRITABLE_STREAM("stdout");
}
if (!stderr || typeof stderr.write !== "function") {
throw new ERR_CONSOLE_WRITABLE_STREAM("stderr");
}
if (typeof colorMode !== "boolean" && colorMode !== "auto") {
// Match Node: reason lists the accepted values (see
// lib/internal/console/constructor.js).
throw new ERR_INVALID_ARG_VALUE(
"colorMode",
colorMode,
"must be one of: 'auto', true, false",
);
}
if (groupIndentation !== undefined) {
validateInteger(
groupIndentation,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass a Node-style writable: new Console({ stdout: process.stdout }) or fs.createWriteStream(path)
- For file logging: const out = fs.createWriteStream('./app.log', { flags: 'a' }); new Console({ stdout: out, stderr: out })
- Adapt web streams with a thin wrapper: { write(chunk) { writer.write(chunk); } } forwarding to a WritableStreamDefaultWriter
- Validate config before constructing: if (typeof opts.stdout?.write !== 'function') throw a descriptive configuration error
Example fix
// before
const { Console } = require('node:console');
const logger = new Console({ stdout: '/tmp/app.log' }); // ERR_CONSOLE_WRITABLE_STREAM
// after
const fs = require('node:fs');
const out = fs.createWriteStream('/tmp/app.log', { flags: 'a' });
const logger = new Console({ stdout: out, stderr: out }); Defensive patterns
Strategy: validation
Validate before calling
function makeConsole(opts) {
const { stdout, stderr } = opts ?? {};
if (typeof stdout?.write !== 'function') {
throw new TypeError('Console options.stdout must be a Node writable stream');
}
if (stderr !== undefined && typeof stderr?.write !== 'function') {
throw new TypeError('Console options.stderr must be a Node writable stream');
}
return new Console(opts);
} Type guard
const isNodeWritable = (v) => v != null && typeof v.write === 'function';
Try / catch
try {
logger = new Console(opts);
} catch (e) {
if (e?.code === 'ERR_CONSOLE_WRITABLE_STREAM') logger = new Console({ stdout: process.stdout });
else throw e;
} Prevention
- Never pass file paths or web streams to Console - wrap fs.createWriteStream instead
- Validate logger config once at startup, not per log call
- Convert WHATWG streams at the boundary with a small write() adapter
When it happens
Trigger: new Console({}) with no stdout; new Console({ stdout: {} }) where stdout has no write method; new Console({ stdout: '/tmp/app.log' }) passing a path string; passing a Deno.WritableStream / WritableStream (web stream) which exposes no write function.
Common situations: Building file loggers with node:console and assuming a path option exists; porting Deno-first code that passes web streams into Node APIs; forgetting destructuring defaults when options come from config objects.
Related errors
- ERR_INVALID_ARG_TYPE
- ERR_STREAM_NULL_VALUES
- ERR_INVALID_ARG_TYPE
- ERR_METHOD_NOT_IMPLEMENTED
- ERR_METHOD_NOT_IMPLEMENTED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/1f70b697b2cb44e4.
Report an issue: GitHub.