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

  1. Upgrade pingora-core to the newest release; chunked-parser invariant panics are treated as bugs
  2. Reproduce with the exact origin bytes: log the upstream response via a capture proxy and attach it to a pingora issue
  3. 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

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


AI-assisted analysis of cloudflare/pingora@0046038bd4 (2026-08-16). Data as JSON: /api/errors/cc60b7a6a2b7719e. Report an issue: GitHub.