{"record":{"id":"addf82a81f562d19","repo":"denoland/deno","slug":"input-request-s-body-is-unusable","errorCode":null,"errorMessage":"Input request's body is unusable","messagePattern":"Input request's body is unusable","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/23_request.js","lineNumber":585,"sourceCode":"    // 37.\n    if (init.body !== undefined && init.body !== null) {\n      const res = extractBody(init.body);\n      initBody = res.body;\n      if (res.contentType !== null && !this[_headers].has(\"content-type\")) {\n        this[_headers].append(\"Content-Type\", res.contentType);\n      }\n    }\n\n    // 38.\n    const inputOrInitBody = initBody ?? inputBody;\n\n    // 40.\n    let finalBody = inputOrInitBody;\n\n    // 41.\n    if (initBody === null && inputBody !== null) {\n      if (input[_body] && input[_body].unusable()) {\n        throw new TypeError(\"Input request's body is unusable\");\n      }\n      finalBody = inputBody.createProxy();\n    }\n\n    // 42.\n    request.body = finalBody;\n  }\n\n  get method() {\n    webidl.assertBranded(this, RequestPrototype);\n    if (this[_method]) {\n      return this[_method];\n    }\n    this[_method] = this[_request].method;\n    return this[_method];\n  }\n\n  get url() {","sourceCodeStart":567,"sourceCodeEnd":603,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/23_request.js#L567-L603","documentation":"Request constructor step 41: when no new body is supplied in init but the input Request has one, the input's body must be teed via createProxy(). A body stream that is already disturbed or locked (previously read, or currently being read) is unusable, and re-using it throws TypeError \"Input request's body is unusable\". A request's body can only be consumed once.","triggerScenarios":"const r = new Request(url, { method: \"POST\", body: data }); await r.text(); new Request(r); also re-using a request whose stream is mid-read (piped to a WritableStream) as input to a new Request.","commonSituations":"Peeking at a body (logging/parsing) then trying to forward the same request object; retry logic that re-wraps an already-read request; middleware that reads the body and later constructs a new Request from the original.","solutions":["Call input.clone() BEFORE reading the body, then build the new Request from the clone","Read the body once into memory (await req.text()) and construct fresh Requests with that string as body","Never re-use a request object after awaiting any body-reading method (text/json/arrayBuffer/formData)"],"exampleFix":"// before\nconst src = new Request(url, { method: \"POST\", body: payload });\nawait src.text(); // log the body\nconst fwd = new Request(src); // throws: body unusable\n\n// after\nconst src = new Request(url, { method: \"POST\", body: payload });\nconst copy = src.clone(); // tee before reading\nawait src.text(); // log the body\nconst fwd = new Request(copy); // ok","handlingStrategy":"validation","validationCode":"if (input instanceof Request && input.bodyUsed) {\n  throw new Error(\"Input request body already consumed — pass the payload string instead\");\n}\nconst req = new Request(input);","typeGuard":"function isReusableRequestBody(req: Request): boolean {\n  return !req.bodyUsed && req.body !== null ? !req.body.locked : true;\n}","tryCatchPattern":"try {\n  const fwd = new Request(input);\n} catch (err) {\n  if (err instanceof TypeError && err.message.includes(\"body is unusable\")) {\n    // body already read: build a fresh request from the buffered payload\n    new Request(url, { method, headers, body: bufferedPayload });\n  } else throw err;\n}","preventionTips":["Clone a request before reading its body if you need to forward it later","Track bodyUsed on requests you pass around; treat true as single-use-consumed","Buffer small bodies (text) once and rebuild requests from the string"],"tags":["fetch","request","body","stream"],"backgroundTag":"body-already-consumed","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}