{"record":{"id":"ac23add43ff4e437","repo":"denoland/deno","slug":"err-invalid-arg-type-ac23ad","errorCode":"ERR_INVALID_ARG_TYPE","errorMessage":"ERR_INVALID_ARG_TYPE(\"stream\", \"Writable\", stream)","messagePattern":"ERR_INVALID_ARG_TYPE\\(\"stream\", \"Writable\", stream\\)","errorType":"validation","errorClass":"ERR_INVALID_ARG_TYPE","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/readline/promises.mjs","lineNumber":42,"sourceCode":"const { ERR_INVALID_ARG_TYPE } = core.loadExtScript(\n  \"ext:deno_node/internal/errors.ts\",\n);\n\nconst {\n  kClearToLineBeginning,\n  kClearToLineEnd,\n  kClearLine,\n  kClearScreenDown,\n} = CSI;\n\nclass Readline {\n  #autoCommit = false;\n  #stream;\n  #todo = [];\n\n  constructor(stream, options = undefined) {\n    if (!isWritable(stream)) {\n      throw new ERR_INVALID_ARG_TYPE(\"stream\", \"Writable\", stream);\n    }\n    this.#stream = stream;\n    if (options?.autoCommit != null) {\n      validateBoolean(options.autoCommit, \"options.autoCommit\");\n      this.#autoCommit = options.autoCommit;\n    }\n  }\n\n  /**\n   * Moves the cursor to the x and y coordinate on the given stream.\n   * @param {integer} x\n   * @param {integer} [y]\n   * @returns {Readline} this\n   */\n  cursorTo(x, y = undefined) {\n    validateInteger(x, \"x\");\n    if (y != null) validateInteger(y, \"y\");\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/readline/promises.mjs#L24-L60","documentation":"The Readline helper class in node:readline/promises (used for cursor control on a single output stream) requires its constructor argument to be a Writable stream. The polyfill checks isWritable(stream) from internal/streams/utils and throws ERR_INVALID_ARG_TYPE('stream', 'Writable', stream) for anything else — strings, numbers, readables like process.stdin or fs.createReadStream().","triggerScenarios":"new Readline(process.stdin); new Readline('out.txt'); new Readline(fs.createReadStream(p)); passing the interface itself or null where a Writable is expected; forgetting the argument so stream is undefined.","commonSituations":"Confusing input/output when wiring terminal helpers (stream must be the output side, e.g. process.stdout); passing a file path string instead of a write stream; using the Readline class where createInterface({ input, output }) was intended.","solutions":["Pass a Writable: process.stdout, process.stderr, or fs.createWriteStream(path)","If you meant a full prompt interface, use createInterface({ input, output }) instead of new Readline(stream)","Check the argument: typeof stream?.write === 'function' before constructing"],"exampleFix":"// before\nconst rl = new Readline('log.txt');\n\n// after\nconst rl = new Readline(fs.createWriteStream('log.txt'));","handlingStrategy":"type-guard","validationCode":"import { Readline } from 'node:readline/promises';\n\nfunction makeReadline(stream: unknown) {\n  if (stream && typeof (stream as NodeJS.WritableStream).write === 'function') {\n    return new Readline(stream as NodeJS.WritableStream);\n  }\n  throw new TypeError('stream must be a Writable (e.g. process.stdout)');\n}","typeGuard":"const isNodeWritable = (s: unknown): s is NodeJS.WritableStream =>\n  !!s && typeof (s as NodeJS.WritableStream)?.write === 'function';","tryCatchPattern":"try {\n  rl = new Readline(stream);\n} catch (err) {\n  if (err?.code === 'ERR_INVALID_ARG_TYPE' && /Writable/.test(err.message)) {\n    rl = new Readline(process.stdout);\n  } else throw err;\n}","preventionTips":["Pass the output side (process.stdout / a write stream), never an input or a path string","For full prompting use createInterface({ input, output }), not new Readline()"],"tags":["readline","promises","node-compat","deno","streams"],"backgroundTag":"invalid-argument-type","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}