nodejs/node · error · InvalidReturnValueError
UND_ERR_INVALID_RETURN_VALUE
UND_ERR_INVALID_RETURN_VALUE
Error message
expected Writable
What it means
Thrown by undici's StreamHandler (InvalidReturnValueError, code UND_ERR_INVALID_RETURN_VALUE) at response time when the factory function returns a value that is missing .write, .end, or .on. The factory must return a Node.js Writable stream so the response body can be pumped into it. Returning null, a string, a Promise, or a non-stream object triggers this.
Source
Thrown at deps/undici/src/lib/api/api-stream.js:164
if (factory === null) {
return
}
const res = this.runInAsyncScope(factory, null, {
statusCode,
headers: responseHeaderData,
opaque,
context
})
if (
!res ||
typeof res.write !== 'function' ||
typeof res.end !== 'function' ||
typeof res.on !== 'function'
) {
throw new InvalidReturnValueError('expected Writable')
}
trackWritableLifecycle(res, (err, fromErrorEvent) => {
const { callback, res, opaque, trailers, abort } = this
this.res = null
if (err || !res?.readable) {
util.destroy(res, fromErrorEvent ? undefined : err)
}
this.callback = null
this.runInAsyncScope(callback, null, err || null, { opaque, trailers })
if (err) {
abort(err)
}
})
View on GitHub (pinned to 1b2de5e052)
Solutions
- Ensure the factory is synchronous and returns a Node Writable with write/end/on (e.g. fs.createWriteStream, stream.Writable, http.ServerResponse).
- If the factory must be async, create the Writable synchronously inside it and resolve setup asynchronously rather than returning a Promise.
- Confirm the returned object is not a WHATWG WritableStream — convert via stream.Writable.fromWeb() if needed.
Example fix
// before
stream(opts, async ({ statusCode }) => fs.createWriteStream(path), cb) // async -> Promise
// after
stream(opts, ({ statusCode }) => fs.createWriteStream(path), cb) Defensive patterns
Strategy: try-catch
Validate before calling
function wrapFactory(f) {
return (ctx) => {
const res = f(ctx)
if (!res || typeof res.write !== 'function' || typeof res.end !== 'function' || typeof res.on !== 'function') {
throw new Error('factory must return a Node Writable')
}
return res
}
}
// stream(opts, wrapFactory(myFactory), cb) Type guard
function isNodeWritable(v) {
return !!v && typeof v.write === 'function' && typeof v.end === 'function' && typeof v.on === 'function'
} Try / catch
try {
stream(opts, factory, cb)
} catch (e) {
if (e.code === 'UND_ERR_INVALID_RETURN_VALUE') {
// factory returned a non-Writable; fix it to return a Node Writable and retry
} else throw e
} Prevention
- Keep the factory synchronous and always return a Node Writable (fs.createWriteStream, stream.Writable, http.ServerResponse).
- Never return a Promise or a WHATWG WritableStream from the factory.
- Add a unit test asserting the factory's return value passes the write/end/on shape check.
When it happens
Trigger: Factory returns undefined (e.g. forgot return), returns a Promise<Writable> (async factory), returns an object literal, or returns a web ReadableStream/WritableStream (WHATWG) instead of a Node stream.
Common situations: Async factory functions whose returned stream is awaited implicitly; returning fs.createWriteStream conditionally such that some branches return nothing; mixing up Web Streams API with Node streams.
Related errors
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/bf29acf548b6b9d0.
Report an issue: GitHub.