cloudflare/pingora · error
body buf exists once a partial chunk head was buffered
Error message
body buf exists once a partial chunk head was buffered
What it means
During chunked transfer-encoding parsing, when only a partial chunk header was buffered, do_read_chunked_body compacts the partial head in place and .expect()s the body buffer to exist ('body buf exists once a partial chunk head was buffered', body.rs:522). The invariant is that buffering a partial head implies body_buf was allocated; the panic means the reader entered the partial-head state with no buffer — an internal parser state violation.
Source
Thrown at pingora-core/src/protocols/http/v1/body.rs:522
.or_err(ReadError, "when reading body")?;
}
} else {
/* existing_buf_end != 0 this is partial chunk head */
/* copy the #expecting_from_io bytes until index existing_buf_end
* to the front and read more to form a valid chunk head.
* existing_buf_end is the end of the partial head and
* expecting_from_io is the len of it.
* Unlike the pipeline handoff this compacts in place rather than
* split_off()-ing at the head. The head is capped at
* PARTIAL_CHUNK_HEAD_LIMIT and is normally a few bytes, so the move is
* bounded and cheap, while split_off() would leave only
* capacity - partial_head_start of room behind it and force the reserve
* below to move the same bytes anyway (or reallocate) to fit the read. */
self.reserve_buf_for_io();
let body_buf = self
.body_buf
.as_mut()
.expect("body buf exists once a partial chunk head was buffered");
let partial_head_start = existing_buf_end - expecting_from_io;
if partial_head_start != 0 {
body_buf.copy_within(partial_head_start..existing_buf_end, 0);
}
body_buf.truncate(expecting_from_io);
// Commit the compacted offsets before awaiting so cancellation leaves the
// parser and buffer in a state that the next call can safely resume.
self.body_state = self
.body_state
.partial_chunk_head(expecting_from_io, expecting_from_io);
let new_bytes = stream
.take((self.body_buf_size - expecting_from_io) as u64)
.read_buf(body_buf)
.await
.or_err(ReadError, "when reading body")?;
if new_bytes == 0 {
self.body_state = self.body_state.done(0);
return Error::e_explain(View on GitHub (pinned to 0046038bd4)
Solutions
- Upgrade pingora-core to the newest release; chunked-parser invariant panics are treated as bugs
- Reproduce with the exact origin bytes: log the upstream response via a capture proxy and attach it to a pingora issue
- As containment, route the offending origin through a non-chunked path (disable chunked upstream or terminate at an intermediary) while the fix lands
Example fix
# before pingora-core = "0.7" # after cargo update -p pingora-core # pick up chunked parser fixes
Defensive patterns
Strategy: try-catch
Try / catch
// Isolate per-connection parsing; a panic becomes a 502/reset for that stream only
let task = tokio::spawn(conn_handler(stream));
if task.await.unwrap_err().is_panic() {
log::error!("chunked parser panicked for peer {peer}"); // keep the proxy alive
} Prevention
- Fuzz chunked transfer-encoding inputs (split chunk heads across segment boundaries) in CI
- Do not share or manually reset session body buffers from custom filters while parsing is in flight
- Monitor panic counts per release; regressions in H1 parsing show up as spikes
When it happens
Trigger: A chunked HTTP/1.1 upstream response whose chunk-size line arrives split across TCP segments in a way that drives the parser into PartialChunkHead state without the expected buffer, or library misuse that desynchronizes body_state from body_buf. Fires mid-body while proxying.
Common situations: Malformed or adversarial chunked responses (fuzzers, broken origin servers); version upgrades that changed parser state transitions; concurrent manipulation of the session between awaits.
Related errors
- body buf exists once a chunk was parsed out of it
- must have read body buf
- body buf is initialized before reading trailers
- take_write_lock() called without cache lock
- take_write_lock() called without lock
AI-assisted analysis of cloudflare/pingora@0046038bd4 (2026-08-16).
Data as JSON: /api/errors/cc60b7a6a2b7719e.
Report an issue: GitHub.