vectordotdev/vector · error
entry must exist
Error message
entry must exist
What it means
After possibly inserting a new `MessageState`, `decode_chunk` re-reads the message from `pending.messages` and asserts with `expect("entry must exist")` that it is present. This is an internal invariant: the code either just inserted the entry or verified it exists earlier (the `is_new_message` check), both under the same held lock, so absence means a logic bug.
Solutions
- Audit recent changes to `decode_chunk`: ensure the insert (or the contains_key check) executes before this lookup under the same lock guard
- Verify `message_id` is not mutated or cloned inconsistently between check and lookup
- Replace the `expect` with proper error propagation if the invariant cannot be guaranteed
Example fix
// before
let message_state = pending.messages.get(&message_id).expect("entry must exist");
// after
let message_state = pending.messages.get(&message_id).ok_or_else(||
ChunkedGelfDecoderError::InternalState { message_id: message_id.clone() })?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: verify message presence before re-lookup (mirrors decoder invariant)
assert!(pending.messages.contains_key(&message_id), "message state missing for id {message_id:?}"); Type guard
fn message_state_exists(pending: &PendingMessages, id: &MessageId) -> bool {
pending.messages.contains_key(id)
} Try / catch
let message_state = pending.messages.get(&message_id)
.ok_or_else(|| ChunkedGelfDecoderError::InternalState { message_id: message_id.clone() })?; Prevention
- Keep insert/check/lookup within one lock-held region in decode_chunk
- Write unit tests covering new-message, duplicate-chunk, and completion paths
- Avoid refactors that drop the mutex guard between the check and the lookup
When it happens
Trigger: Calling `decode_chunk` (via `decode_message`) when the map lookup after insert/check returns None — theoretically impossible while the lock is held; would require a bug in the insertion/check logic or lock-escaping mutation.
Common situations: Effectively only hit by developers modifying the decoder (e.g. moving the insert, changing the ID type, or dropping the lock mid-function) and breaking the invariant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- a record with a next ID must have an event count
- a validated HTTP endpoint is a valid `http 1` URI
- Buffered payload limit of
- Default maximum data file size should never be greater than…
- `docker_logs.stream` must exist in the metadata
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/ad34c7b38535b0ec.
Report an issue: GitHub.
Appendix: source
Thrown at lib/codecs/src/decoding/framing/chunked_gelf.rs:521
let owns_message = pending
.messages
.get(&message_id)
.is_some_and(|message| message.timeout_task.id() == timeout_task_id);
if owns_message && pending.remove(message_id).is_some() {
warn!(
message_id = message_id,
timeout_secs = timeout.as_secs_f64(),
"Message was not fully received within the timeout window. Discarding it."
);
}
});
pending.messages.insert(
message_id,
Box::new(MessageState::new(total_chunks, timeout_handle)),
);
}
let message_state = pending.messages.get(&message_id).expect("entry must exist");
ensure!(
message_state.total_chunks == total_chunks,
TotalChunksMismatchSnafu {
message_id,
sequence_number,
original_total_chunks: message_state.total_chunks,
received_total_chunks: total_chunks
}
);
if message_state.is_chunk_present(sequence_number) {
debug!(
message_id = message_id,
sequence_number = sequence_number,
"Received a duplicate chunk. Ignoring it."
);
return Ok(None);View on GitHub (pinned to bdb87aeaa4)