vectordotdev/vector · error · ChunkedGelfDecoderError
Invalid chunk header with less than 10 bytes: 0x{header:0x}
Error message
Invalid chunk header with less than 10 bytes: 0x{header:0x} What it means
The chunked GELF decoder requires at least 10 bytes after the 2-byte magic (`0x1e 0x0f`): an 8-byte message id, 1-byte sequence number, and 1-byte total chunks. If a datagram reaches `get_pending_chunk`'s header parse with fewer than 10 bytes remaining, the `ensure!` fires `InvalidChunkHeaderSnafu` and the decoded datagram is rejected with `Invalid chunk header with less than 10 bytes: 0x{header}`. It is a per-datagram decode error, not a crash.
Source
Thrown at lib/codecs/src/decoding/framing/chunked_gelf.rs:343
pub fn decode_chunk(
&mut self,
mut chunk: Bytes,
) -> Result<Option<Bytes>, ChunkedGelfDecoderError> {
// Encoding scheme:
//
// +------------+-----------------+--------------+----------------------+
// | Message id | Sequence number | Total chunks | Chunk payload |
// +------------+-----------------+--------------+----------------------+
// | 64 bits | 8 bits | 8 bits | remaining bits |
// +------------+-----------------+--------------+----------------------+
//
// As this codec is oriented for UDP, the chunks (datagrams) are not guaranteed to be received in order,
// nor to be received at all. So, we have to store the chunks in a buffer (state field) until we receive
// all the chunks of a message. When we receive all the chunks of a message, we can concatenate them
// and return the complete payload.
// We need 10 bytes to read the message id, sequence number and total chunks
ensure!(
chunk.remaining() >= 10,
InvalidChunkHeaderSnafu { header: chunk }
);
let message_id = chunk.get_u64();
let sequence_number = chunk.get_u8();
let total_chunks = chunk.get_u8();
ensure!(
total_chunks > 0 && total_chunks <= GELF_MAX_TOTAL_CHUNKS,
InvalidTotalChunksSnafu {
message_id,
sequence_number,
total_chunks
}
);
ensure!(View on GitHub (pinned to 99894c8d88)
Solutions
- Verify the sender actually emits the GELF chunked format (`0x1e 0x0f` + 8-byte id + seq + total + payload) with a capture (tcpdump) before the change.
- Point non-GELF traffic at a different port/source so it cannot be mistaken for chunked GELF.
- Fix or upgrade the producing library that emits malformed chunk headers.
Defensive patterns
Strategy: try-catch
Try / catch
match decoder.decode(&mut buf).await {
Ok(Some(bytes)) => { /* forward */ }
Ok(None) => {}
Err(e) if e.to_string().contains("Invalid chunk header") => {
// malformed datagram: log and drop, keep the source alive
warn!(error = %e, "dropping malformed GELF chunk");
}
Err(e) => return Err(e.into()),
} Prevention
- Dedicate one UDP port per protocol; never share it between GELF and other binary traffic.
- tcpdump the input when first enabling chunked GELF to confirm header layout.
- Treat per-chunk framing errors as drop-and-continue, not fatal.
When it happens
Trigger: A UDP datagram whose payload matches the chunked-GELF magic but is truncated (2–11 bytes total), or random binary/non-GELF traffic on the same port that happens to begin with `0x1e 0x0f`; also MTU-sized re-sends that get cut off mid-header.
Common situations: Port reuse where another protocol's binary traffic lands on the GELF input; buggy GELF senders (custom libraries) that emit the magic then an undersized header; network equipment truncating tiny datagrams.
Related errors
- Received chunk with message id {message_id} and sequence num
- Received chunk with message id {message_id} and sequence num
- InvalidData
- Pending messages limit of {pending_messages_limit} reached w
- Received chunk with message id {message_id} and sequence num
AI-assisted analysis of vectordotdev/vector@99894c8d88 (2026-08-20).
Data as JSON: /api/errors/0fd14e916d2ed0bc.
Report an issue: GitHub.