{"record":{"id":"1e1e1b8f724d5047","repo":"denoland/deno","slug":"readablestream-is-locked-1e1e1b","errorCode":null,"errorMessage":"ReadableStream is locked","messagePattern":"ReadableStream is locked","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/06_streams.js","lineNumber":4510,"sourceCode":"  setUpReadableStreamDefaultController(\n    stream,\n    controller,\n    startAlgorithm,\n    pullAlgorithm,\n    cancelAlgorithm,\n    highWaterMark,\n    sizeAlgorithm,\n  );\n}\n\n/**\n * @template R\n * @param {ReadableStreamBYOBReader} reader\n * @param {ReadableStream<R>} stream\n */\nfunction setUpReadableStreamBYOBReader(reader, stream) {\n  if (isReadableStreamLocked(stream)) {\n    throw new TypeError(\"ReadableStream is locked\");\n  }\n  if (\n    !(ObjectPrototypeIsPrototypeOf(\n      ReadableByteStreamControllerPrototype,\n      stream[_controller],\n    ))\n  ) {\n    throw new TypeError(\"Cannot use a BYOB reader with a non-byte stream\");\n  }\n  readableStreamReaderGenericInitialize(reader, stream);\n  reader[_readIntoRequests] = new Queue();\n}\n\n/**\n * @template R\n * @param {ReadableStreamDefaultReader<R>} reader\n * @param {ReadableStream<R>} stream\n */","sourceCodeStart":4492,"sourceCodeEnd":4528,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/06_streams.js#L4492-L4528","documentation":"A ReadableStreamBYOBReader (new ReadableStreamBYOBReader(stream) or stream.getReader({ mode: 'byob' })) was attached to a stream that is already locked. ReadableStream allows exactly one active reader or one active pipe at a time; stream.locked === true means a reader, getReader(), or pipeTo/pipeThrough currently owns it.","triggerScenarios":"Calling getReader() earlier and then getReader({ mode: 'byob' }); a pipeTo()/pipeThrough() still running on the stream while acquiring a reader; a previous reader whose releaseLock() was never called.","commonSituations":"Wrapping a stream that user code already reads; middleware that takes a stream and internally calls getReader(); inspection/tee wrappers that acquire a reader and forget to release it.","solutions":["Reuse the existing reader instead of acquiring a second one.","Call reader.releaseLock() on the previous reader before attaching a new one.","Await completion of any active pipeTo/pipeThrough before calling getReader().","Use stream.tee() when two independent consumers must read the same data."],"exampleFix":"// before\nconst r1 = stream.getReader();\nconst r2 = stream.getReader({ mode: 'byob' }); // TypeError: ReadableStream is locked\n\n// after\nconst r1 = stream.getReader();\n// ... finish reading ...\nr1.releaseLock();\nconst r2 = stream.getReader({ mode: 'byob' }); // ok","handlingStrategy":"validation","validationCode":"if (stream.locked) {\n  throw new Error('stream already has a reader or active pipe — release it first');\n}\nconst reader = stream.getReader({ mode: 'byob' });","typeGuard":null,"tryCatchPattern":"try {\n  reader = stream.getReader({ mode: 'byob' });\n} catch (e) {\n  if (e instanceof TypeError && e.message === 'ReadableStream is locked') {\n    previousReader.releaseLock(); // release the known prior holder, then retry once\n    reader = stream.getReader({ mode: 'byob' });\n  } else throw e;\n}","preventionTips":["One reader per stream at a time; call releaseLock() in a finally block.","Check stream.locked before getReader() in adapter code.","Pass readers, not streams, through APIs to make ownership explicit."],"tags":["readable-stream","byob-reader","locked-stream","reader"],"backgroundTag":"readable-stream-locked","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}