{"record":{"id":"bc49ff6d3dcaa19a","repo":"nodejs/node","slug":"und-err-invalid-return-value","errorCode":"UND_ERR_INVALID_RETURN_VALUE","errorMessage":"expected Readable","messagePattern":"expected Readable","errorType":"validation","errorClass":"InvalidReturnValueError","httpStatus":null,"severity":"error","filePath":"deps/undici/src/lib/api/api-pipeline.js","lineNumber":203,"sourceCode":"      this.handler = null\n      const rawHeaders = controller?.rawHeaders\n      const responseHeaders = this.responseHeaders === 'raw'\n        ? util.parseRawHeaders(rawHeaders)\n        : headers\n      body = this.runInAsyncScope(handler, null, {\n        statusCode,\n        headers: responseHeaders,\n        opaque,\n        body: this.res,\n        context\n      })\n    } catch (err) {\n      this.res.on('error', noop)\n      throw err\n    }\n\n    if (!body || typeof body.on !== 'function') {\n      throw new InvalidReturnValueError('expected Readable')\n    }\n\n    body\n      .on('data', (chunk) => {\n        const { ret, body } = this\n\n        if (!ret.push(chunk) && body.pause) {\n          body.pause()\n        }\n      })\n      .on('error', (err) => {\n        const { ret } = this\n\n        util.destroy(ret, err)\n      })\n      .on('end', () => {\n        const { ret } = this\n","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/undici/src/lib/api/api-pipeline.js#L185-L221","documentation":"Thrown by undici's PipelineHandler (code UND_ERR_INVALID_RETURN_VALUE) when the user-supplied handler returns a value that is null/undefined or lacks an 'on' method — i.e. not a Readable stream. pipeline() pumps the response body into the stream returned by the handler, so the return value MUST be a Readable (or have Readable-like .on('data'|'error'|'end')). This is a contract violation by the handler implementation, not a network error.","triggerScenarios":"pipeline() handler that returns undefined (forgot return), a string, a Promise, an object literal, or a Writable-only stream without .on. Any of these causes onResponseStart to throw 'expected Readable'.","commonSituations":"Handler returns nothing after `await`; handler returns the response object itself instead of a transformed stream; handler returns a Promise of a stream (pipeline does not await); passing a sink/Writable where a Readable is required.","solutions":["Ensure the handler returns a Readable stream — typically create one with new PassThrough()/Readable.from() and return it.","Do not return a Promise; do the work synchronously and return the stream, or pipe inside the handler.","If transforming, read from the provided res.body and push into a Readable you create and return.","Verify the returned object has .on('data')/.on('error')/.on('end')."],"exampleFix":"// before\nundici.pipeline(url, {}, ({ body }) => {\n  body.on('data', () => {})   // returns undefined -> 'expected Readable'\n})\n// after\nconst { PassThrough } = require('node:stream')\nundici.pipeline(url, {}, ({ body }) => {\n  const pass = new PassThrough()\n  body.pipe(pass)\n  return pass\n})","handlingStrategy":"type-guard","validationCode":"function ensureReadable(ret) {\n  if (!ret || typeof ret.on !== 'function') throw new TypeError('pipeline handler must return a Readable stream')\n  return ret\n}","typeGuard":"function isReadableLike(v: unknown): v is NodeJS.ReadableStream {\n  return !!v && typeof (v as any).on === 'function'\n}","tryCatchPattern":"// pipeline throws synchronously inside the handler scope; wrap handler body:\nundici.pipeline(url, opts, (res) => {\n  try {\n    const ret = transform(res)\n    if (!ret || typeof ret.on !== 'function') throw new TypeError('handler must return a Readable')\n    return ret\n  } catch (err) { console.error(err); throw err }\n})","preventionTips":["Always return a Readable (e.g. new PassThrough()) from the handler.","Do not return a Promise — do work synchronously or pipe inside.","Pipe the incoming res.body into the returned stream.","Unit-test the handler in isolation to assert it returns a value with .on."],"tags":["undici","pipeline","stream","readable","return-value","validation"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}