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

  1. Audit recent changes to `decode_chunk`: ensure the insert (or the contains_key check) executes before this lookup under the same lock guard
  2. Verify `message_id` is not mutated or cloned inconsistently between check and lookup
  3. 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

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


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)