vectordotdev/vector · error · ChunkedGelfDecoderError::BufferedPayloadLimitReached
Buffered payload limit of
Error message
Buffered payload limit of {limit} bytes reached while processing chunk with message id {message_id} and sequence number {sequence_number}. Discarding all buffered chunks of that message. What it means
Beyond counting pending messages, the chunked GELF decoder bounds total buffered bytes per incomplete message via `max_buffered_payload`. Before appending a chunk, it checks `pending.buffered_payload + chunk_len <= max_buffered_payload` (saturating add) and, if exceeded, fails with this error and discards all buffered chunks of that message. This prevents a single oversized or repeatedly re-sent message id from exhausting memory.
Solutions
- Increase `max_buffered_payload` in the source configuration to accommodate your largest legitimate chunked GELF messages.
- Split oversized messages at the sender or send them via a non-chunked transport (TCP GELF) instead.
- Check for packet loss/duplication causing the same message id to be retransmitted and inflate the buffer.
- Note the affected message's buffered chunks are discarded on this error — retransmission must come from the sender.
Example fix
# before
sources:
gelf:
decoding:
chunked_gelf:
max_buffered_payload: 65535
# after
sources:
gelf:
decoding:
chunked_gelf:
max_buffered_payload: 1048576 Defensive patterns
Strategy: fallback
Validate before calling
// ensure the largest message fits the buffer
let max_msg_bytes = total_chunks_max * chunk_size;
assert!(max_msg_bytes <= max_buffered_payload,
"max_buffered_payload must be at least {max_msg_bytes} bytes"); Try / catch
match framing.decode(&datagram) {
Err(e) if e.to_string().contains("Buffered payload limit") => {
// chunks of this message were discarded; rely on sender retransmission
warn!("oversized/duplicated GELF message dropped: {e}");
metrics.incr("gelf_payload_limit_hit");
}
other => { /* handle normally */ }
} Prevention
- Set `max_buffered_payload` above your largest legitimate chunked message.
- Send very large payloads over TCP GELF or split them at the source.
- Watch for duplicate re-sends of the same message id (lossy networks) that inflate the buffer.
When it happens
Trigger: decode_chunk receives a chunk for an existing pending message where adding the chunk's length to `pending.buffered_payload` (saturating) would exceed `self.max_buffered_payload` — either very large accumulated messages or the same message id being re-sent repeatedly due to loss.
Common situations: A sender emitting GELF messages larger than the configured buffer allows; severe packet loss causing duplicate re-sends of the same message id that inflate the buffered payload; a too-low `max_buffered_payload` setting relative to legitimate message sizes.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- Pending messages limit of
- Invalid chunk header with less than 10 bytes: 0x
- Received chunk with message id
- Received chunk with message id
- Received chunk with message id
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/f83b6296b7faec99.
Report an issue: GitHub.
Appendix: source
Thrown at lib/codecs/src/decoding/framing/chunked_gelf.rs:486
// applies only on insert, since rejecting chunks of pending messages would stall them.
if is_new_message {
if chunk_len > self.max_length {
return Err(ChunkedGelfDecoderError::MaxLengthExceed {
message_id,
sequence_number,
length: chunk_len,
max_length: self.max_length,
});
}
ensure!(
pending.messages.len() < self.pending_messages_limit,
PendingMessagesLimitReachedSnafu {
message_id,
sequence_number,
pending_messages_limit: self.pending_messages_limit
}
);
ensure!(
pending.buffered_payload.saturating_add(chunk_len) <= self.max_buffered_payload,
BufferedPayloadLimitReachedSnafu {
message_id,
sequence_number,
limit: self.max_buffered_payload,
}
);
}
if is_new_message {
let state = Arc::clone(&self.state);
let timeout = self.timeout;
let timeout_handle = tokio::spawn(async move {
tokio::time::sleep(timeout).await;
let timeout_task_id = tokio::task::id();
let mut pending = state.lock().expect("poisoned lock");
let owns_message = pending
.messagesView on GitHub (pinned to bdb87aeaa4)