actix/actix-web · error
cannot reuse response builder
Error message
cannot reuse response builder
What it means
This is a runtime panic from `HttpResponseBuilder::extensions()`. The builder stores the response in an `Option<Response<BoxBody>>`; after a terminal method like `.body()`, `.finish()`, `.json()`, or `.streaming()` consumes the inner response via `.take()`, calling `.extensions()` finds `None` and panics with `.expect("cannot reuse response builder")` at line 272.
Solutions
- Access `.extensions()` before calling any terminal method (`.body()`, `.finish()`, etc.)
- Use `.take()` to split the builder into a new instance if you need to access state after building
- Return the response immediately after building; do not continue to use the builder
- Access extensions on the built `HttpResponse` instead: `res.extensions()`
Example fix
// before
let mut builder = HttpResponse::Ok();
builder.insert_header(("X-Test", "1"));
let res = builder.finish();
let ext = builder.extensions(); // panics
// after
let mut builder = HttpResponse::Ok();
builder.insert_header(("X-Test", "1"));
let ext = builder.extensions(); // before finish
let res = builder.finish(); Defensive patterns
Strategy: validation
Validate before calling
// Access extensions before calling any terminal method.
// Structure handlers to call .finish()/.body() last.
async fn handler(req: HttpRequest) -> HttpResponse {
let mut builder = HttpResponse::Ok();
builder.extensions_mut().insert(MyData { id: 42 }); // before finish
builder.insert_header(("X-Custom", "value"));
builder.finish() // terminal call, last
} Try / catch
// Rust does not catch panics. Ensure .extensions() is called before .finish()/.body(). // If you need extensions after building, use the HttpResponse directly: let res = HttpResponse::Ok().finish(); // Access on the response, not the builder: let ext = res.extensions();
Prevention
- Call .extensions() before any terminal method (.finish(), .body(), .json(), .streaming())
- Access extensions on the built HttpResponse instead of the builder after construction
- Use method chaining to make the call order explicit and unambiguous
- Treat .finish()/.body() as the final operation on a builder
When it happens
Trigger: Calling `.extensions()` after `.body()`, `.finish()`, `.json()`, or `.streaming()` on the same builder. Also happens if `.extensions()` is called after `.take()`. For example: `let res = builder.finish(); let ext = builder.extensions();` panics.
Common situations: Storing a builder, calling `.finish()` early (perhaps in a helper), then trying to access extensions later. Also occurs with the `From<HttpResponseBuilder>` impl which calls `.finish()` internally.
Related errors
- cannot reuse response builder
- All default headers must be added before cloning.
- Invalid header name
- Invalid header value
- Value for parameter is not available
AI-assisted analysis of actix/actix-web@4d435abc28 (2026-08-09).
Data as JSON: /api/errors/f379a80f1bd08111.
Report an issue: GitHub.
Appendix: source
Thrown at actix-web/src/response/builder.rs:272
/// .finish();
/// ```
#[cfg(feature = "cookies")]
pub fn cookie(&mut self, cookie: cookie::Cookie<'_>) -> &mut Self {
match cookie.to_string().try_into_value() {
Ok(hdr_val) => self.append_header((header::SET_COOKIE, hdr_val)),
Err(err) => {
self.error = Some(err.into());
self
}
}
}
/// Returns a reference to the response-local data/extensions container.
#[inline]
pub fn extensions(&self) -> Ref<'_, Extensions> {
self.res
.as_ref()
.expect("cannot reuse response builder")
.extensions()
}
/// Returns a mutable reference to the response-local data/extensions container.
#[inline]
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
self.res
.as_mut()
.expect("cannot reuse response builder")
.extensions_mut()
}
/// Set a body and build the `HttpResponse`.
///
/// Unlike [`message_body`](Self::message_body), errors are converted into error
/// responses immediately.
///
/// `HttpResponseBuilder` can not be used after this call.View on GitHub (pinned to 4d435abc28)