{"record":{"id":"a4687de1de0bda58","repo":"microsoft/playwright","slug":"response-body-is-unavailable","errorCode":null,"errorMessage":"Response body is unavailable","messagePattern":"Response body is unavailable","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/chromium/crNetworkManager.ts","lineNumber":595,"sourceCode":"  readonly _originalRequestRoute: RouteImpl | undefined;\n  session: CRSession;\n\n  private static from(request: network.Request): InterceptableRequest | undefined {\n    return (request as any)[kInterceptableRequest];\n  }\n\n  static detachIfNeeded(request: network.Request, session: CRSession) {\n    if (InterceptableRequest.from(request)?.session === session)\n      (request as any)[kInterceptableRequest] = undefined;\n  }\n\n  static createResponseBodyCallback(request: network.Request): () => Promise<Buffer> {\n    return async () => {\n      // Lookup the request lazily, so that the response does not retain the\n      // InterceptableRequest and its session after detachIfNeeded().\n      const interceptable = InterceptableRequest.from(request);\n      if (!interceptable)\n        throw new Error('Response body is unavailable');\n      const contentLength = request._existingResponse()?.headerValue('content-length');\n      const expectedLength = contentLength ? +contentLength : undefined;\n\n      const session = interceptable.session;\n      const response = await session.send('Network.getResponseBody', { requestId: interceptable._requestId });\n      if (response.body || !expectedLength)\n        return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');\n\n      // Make sure no network requests sent while reading the body for fulfilled requests.\n      if (interceptable._originalRequestRoute?._fulfilled)\n        return Buffer.from('');\n\n      // Re-fetching the resource may produce side effects on the server, only\n      // do it for GETs of static subresources and prefetch requests.\n      if (request.method() !== 'GET')\n        return Buffer.from('');\n      if (!kRefetchSafeResourceTypes.has(request.resourceType())) {\n        const rawHeaders = await request.internalRawRequestHeaders();","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/chromium/crNetworkManager.ts#L577-L613","documentation":"Thrown by createResponseBodyCallback (crNetworkManager.ts:595) when InterceptableRequest.from(request) returns undefined — the request has been detached from its CDP session (the symbol was cleared by detachIfNeeded). The response body can no longer be fetched via Network.getResponseBody because there is no session/route binding left.","triggerScenarios":"Calling response.body() after route.fulfill() or route.continue() detached the request; reading the body after the page/context that owned the request was closed; accessing the body of a request whose route was already resolved.","commonSituations":"A request handler that fulfills a route and then logs response.body(); page.on('response') listeners that outlive the page; retries that re-read bodies after fulfill.","solutions":["Read response.body() before fulfilling or continuing the route.","Cache the body bytes in the route handler if you need them later.","Detach-aware: only read the body while the page that produced the response is still open."],"exampleFix":"// before\nroute.fulfill({ status: 200 });\nconst body = await response.body();\n// after\nconst body = await response.body();\nawait route.fulfill({ status: 200, body });","handlingStrategy":"validation","validationCode":"// Read the body BEFORE fulfilling or continuing the route.\nconst response = await route.fetch();\nconst body = await response.body();\nawait route.fulfill({ status: response.status(), body, headers: response.headers() });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat route fulfillment as terminal: read everything you need first.","Do not call response.body() after route.fulfill()/continue().","Cache body bytes in the handler if multiple consumers need them."],"tags":["network","route","response","chromium"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}