{"record":{"id":"646b6ab07fa6ef45","repo":"denoland/deno","slug":"this-byob-request-has-been-invalidated","errorCode":null,"errorMessage":"This BYOB request has been invalidated","messagePattern":"This BYOB request has been invalidated","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/web/06_streams.js","lineNumber":6726,"sourceCode":"    }\n    this[_brand] = _brand;\n  }\n\n  respond(bytesWritten) {\n    webidl.assertBranded(this, ReadableStreamBYOBRequestPrototype);\n    const prefix = \"Failed to execute 'respond' on 'ReadableStreamBYOBRequest'\";\n    webidl.requiredArguments(arguments.length, 1, prefix);\n    bytesWritten = webidl.converters[\"unsigned long long\"](\n      bytesWritten,\n      prefix,\n      \"Argument 1\",\n      {\n        enforceRange: true,\n      },\n    );\n\n    if (this[_controller] === undefined) {\n      throw new TypeError(\"This BYOB request has been invalidated\");\n    }\n\n    let buffer, byteLength;\n    if (isTypedArray(this[_view])) {\n      buffer = TypedArrayPrototypeGetBuffer(this[_view]);\n      byteLength = TypedArrayPrototypeGetByteLength(this[_view]);\n    } else {\n      buffer = DataViewPrototypeGetBuffer(this[_view]);\n      byteLength = DataViewPrototypeGetByteLength(this[_view]);\n    }\n    if (isDetachedBuffer(buffer)) {\n      throw new TypeError(\n        \"The BYOB request's buffer has been detached and so cannot be used as a response\",\n      );\n    }\n    assert(byteLength > 0);\n    assert(getArrayBufferByteLength(buffer) > 0);\n    readableByteStreamControllerRespond(this[_controller], bytesWritten);","sourceCodeStart":6708,"sourceCodeEnd":6744,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/06_streams.js#L6708-L6744","documentation":"respond() (or respondWithNewView()) was called on a ReadableStreamBYOBRequest whose internal controller reference is undefined — the request was invalidated. The controller issues a new BYOBRequest per pending pull-into and invalidates the old one whenever the pending read is fulfilled or shifted (e.g. by a controller.enqueue()), the stream closes, or the request is superseded. Responding on any stale request object throws.","triggerScenarios":"Caching controller.byobRequest in a variable (or on this) and reusing it across pulls; calling respond() twice on the same request; responding on a request that a parallel controller.enqueue() already satisfied; responding after close().","commonSituations":"Source adapters storing byobRequest on the instance for convenience; event-driven code where a late event responds on a superseded request; refactors from per-pull requests to a cached-request design.","solutions":["Read controller.byobRequest fresh at the top of every pull() and respond at most once per non-null request.","Never store the request beyond the current pull's lifetime.","If events can arrive late, re-check controller.byobRequest before responding and drop responses for superseded requests."],"exampleFix":"// before\nclass Source {\n  pull(controller) {\n    if (!this.byob) this.byob = controller.byobRequest; // cached once\n    this.byob.respond(n); // later pull -> TypeError: invalidated\n  }\n}\n\n// after\nclass Source {\n  pull(controller) {\n    const byob = controller.byobRequest; // fresh every pull\n    if (byob === null) return;           // none pending\n    byob.respond(n);\n  }\n}","handlingStrategy":"validation","validationCode":"// always re-derive; the old object is dead after any enqueue/respond/close\nconst byob = controller.byobRequest;\nif (byob === null) return; // request invalidated or none pending\nbyob.respond(n);","typeGuard":null,"tryCatchPattern":"try {\n  byob.respond(n);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('invalidated')) {\n    return; // superseded request — ignore the late response\n  }\n  throw e;\n}","preventionTips":["Treat controller.byobRequest as single-use and pull-scoped.","Exactly one respond/respondWithNewView per request object, ever.","After any enqueue() or close(), previous requests are dead — re-fetch before responding."],"tags":["readable-stream","byob-reader","respond","invalidated","stale-object"],"backgroundTag":"byob-request-invalidated","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}