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

  1. Verify the sender actually emits the GELF chunked format (`0x1e 0x0f` + 8-byte id + seq + total + payload) with a capture (tcpdump) before the change.
  2. Point non-GELF traffic at a different port/source so it cannot be mistaken for chunked GELF.
  3. 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

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


AI-assisted analysis of vectordotdev/vector@99894c8d88 (2026-08-20). Data as JSON: /api/errors/0fd14e916d2ed0bc. Report an issue: GitHub.