{"record":{"id":"bf42cc32d0fbae98","repo":"actix/actix-web","slug":"cannot-reuse-response-builder","errorCode":null,"errorMessage":"cannot reuse response builder","messagePattern":"cannot reuse response builder","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"actix-http/src/responses/builder.rs","lineNumber":223,"sourceCode":"    pub fn body<B>(&mut self, body: B) -> Response<EitherBody<B>>\n    where\n        B: MessageBody + 'static,\n    {\n        match self.message_body(body) {\n            Ok(res) => res.map_body(|_, body| EitherBody::left(body)),\n            Err(err) => Response::from(err).map_body(|_, body| EitherBody::right(body)),\n        }\n    }\n\n    /// Generate response with a body.\n    ///\n    /// This `ResponseBuilder` will be left in a useless state.\n    pub fn message_body<B>(&mut self, body: B) -> Result<Response<B>, Error> {\n        if let Some(err) = self.err.take() {\n            return Err(Error::new_http().with_cause(err));\n        }\n\n        let head = self.head.take().expect(\"cannot reuse response builder\");\n\n        Ok(Response {\n            head,\n            body,\n            extensions: RefCell::new(Extensions::new()),\n        })\n    }\n\n    /// Generate response with an empty body.\n    ///\n    /// This `ResponseBuilder` will be left in a useless state.\n    #[inline]\n    pub fn finish(&mut self) -> Response<EitherBody<()>> {\n        self.body(())\n    }\n\n    /// Create an owned `ResponseBuilder`, leaving the original in a useless state.\n    pub fn take(&mut self) -> ResponseBuilder {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/actix/actix-web/blob/4d435abc281842f3cbee165b6cde739e001d3a25/actix-http/src/responses/builder.rs#L205-L241","documentation":"This is a runtime panic from the actix-http `ResponseBuilder::message_body()` method. The builder uses an `Option<BoxedResponseHead>` internally; calling `message_body()` (or `body()`, `finish()`) takes the head via `self.head.take()` at line 223, leaving it as `None`. A second call to any body-producing method finds `None` and panics via `.expect(\"cannot reuse response builder\")`.","triggerScenarios":"Calling `.body(...)` or `.finish()` twice on the same `ResponseBuilder`, or calling `.body(...)` after `.finish()` (since `finish()` internally calls `body(())`). Also panics if calling any method that accesses `self.inner()` after the head has been taken.","commonSituations":"Storing a `ResponseBuilder` in a variable and conditionally calling `.body()` in different branches where both might execute. Most commonly happens with mutable references shared across code paths.","solutions":["Call `.body()` or `.finish()` exactly once per builder instance","Use `ResponseBuilder::take()` to extract the builder state into a fresh instance if you need to split the flow","Return the response immediately after building it rather than reusing the builder","Use `match` or `if/else` that produces a single `.body()` call at the end of the function"],"exampleFix":"// before\nlet mut builder = ResponseBuilder::new(StatusCode::OK);\nlet res1 = builder.finish();\nlet res2 = builder.finish(); // panics\n\n// after\nlet res = ResponseBuilder::new(StatusCode::OK).finish();","handlingStrategy":"validation","validationCode":"// Track builder usage to prevent reuse. Prefer functional construction.\n// Always build in a single chain to guarantee one terminal call:\nfn build_response(status: actix_http::StatusCode) -> actix_http::Response<actix_http::body::EitherBody<()>> {\n    ResponseBuilder::new(status)\n        .insert_header((\"X-Test\", \"1\"))\n        .finish()\n}","typeGuard":null,"tryCatchPattern":"// Rust does not catch panics in normal code.\n// Ensure .body()/.finish() is called exactly once.\n// If you need conditional logic, structure it so only one terminal call runs:\nlet res = if condition {\n    builder.body(\"data\")\n} else {\n    builder.finish()\n};\n// Do NOT call any builder method after this point.","preventionTips":["Call .body(), .finish(), or .message_body() exactly once per ResponseBuilder","Use method chaining to prevent accidental reuse: ResponseBuilder::new(status).header(...).finish()","Return the built response immediately; do not store and reuse the builder","Use ResponseBuilder::take() if you need to split builder state across code paths"],"tags":["rust","actix-http","response-builder","runtime-panic","api-misuse"],"backgroundTag":null,"analyzedSha":"4d435abc281842f3cbee165b6cde739e001d3a25","analyzedAt":"2026-08-09T01:01:40.926Z","contentChangedAt":"2026-08-09T01:01:40.926Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}