vectordotdev/vector · error
Indexer acknowledgements channel must allow at least one pen
Error message
Indexer acknowledgements channel must allow at least one pending ack
What it means
The splunk_hec acknowledgement tracker caps pending ack ids per channel; when len() exceeds the cap it removes the smallest (oldest) id. The removal is guarded by min() returning None => unreachable, because the config type (NonZeroU64, default 1_000_000) guarantees max_pending_acks_per_channel >= 1 and the set is non-empty whenever len() > cap - the branch cannot fire unless that guarantee is broken.
Source
Thrown at src/sources/splunk_hec/acknowledgements.rs:219
ack_event_finalizer: UnorderedFinalizer<u64>,
}
impl Channel {
fn new(max_pending_acks_per_channel: u64, shutdown: ShutdownSignal) -> Self {
let ack_ids_status = Arc::new(Mutex::new(RoaringTreemap::new()));
let finalizer_ack_ids_status = Arc::clone(&ack_ids_status);
let (ack_event_finalizer, mut ack_stream) = UnorderedFinalizer::new(Some(shutdown));
crate::spawn_in_current_span(async move {
while let Some((status, ack_id)) = ack_stream.next().await {
if status == BatchStatus::Delivered {
let mut ack_ids_status = finalizer_ack_ids_status.lock().unwrap();
ack_ids_status.insert(ack_id);
if ack_ids_status.len() > max_pending_acks_per_channel {
match ack_ids_status.min() {
Some(min) => ack_ids_status.remove(min),
// max pending acks per channel is guaranteed to be >= 1,
// thus there must be at least one ack id available to remove
None => unreachable!(
"Indexer acknowledgements channel must allow at least one pending ack"
),
};
}
}
}
});
Self {
last_used_timestamp: RwLock::new(Instant::now()),
currently_available_ack_id: AtomicU64::new(0),
ack_ids_status,
ack_event_finalizer,
}
}
fn get_ack_id(&self, batch_rx: BatchStatusReceiver) -> u64 {
{View on GitHub (pinned to 3708c39b12)
Solutions
- If embedding, construct via AcknowledgementsConfig (NonZeroU64) or pass a value >= 1 to Channel::new
- Audit any code computing the cap arithmetically before it reaches the channel
- In stock Vector, report it - the NonZeroU64 invariant makes this a bug by definition
- Capture RUST_BACKTRACE=1 output when it fires to identify which construction path passed 0
Example fix
// before
let channel = Channel::new(computed_cap, shutdown); // computed_cap == 0 -> invariant broken
// after
let cap = std::num::NonZeroU64::new(computed_cap.max(1)).unwrap();
let config = AcknowledgementsConfig { max_pending_acks_per_channel: cap, ..Default::default() }; Defensive patterns
Strategy: validation
Validate before calling
// Before enabling acknowledgements, assert the invariant yourself: assert!(u64::from(config.max_pending_acks_per_channel) >= 1); // NonZeroU64 makes this static // and never call Channel::new directly with a computed value below 1
Prevention
- Always source the cap from AcknowledgementsConfig (NonZeroU64), never raw arithmetic
- Keep the default (1_000_000) unless indexer behavior demands otherwise
- Treat this panic as a code bug: capture RUST_BACKTRACE=1 and report
When it happens
Trigger: Only if max_pending_acks_per_channel is 0 or the set/cap invariant breaks: the NonZeroU64 config type prevents 0 through YAML, so in practice this requires code constructing Channel::new with a computed 0 capacity or corrupting ack_ids_status (custom builds, refactors bypassing AcknowledgementsConfig).
Common situations: Custom embeddings building the acknowledgements Channel directly with an arithmetically computed capacity (integer division/underflow to 0); modifications to the ack-id set logic; unreachable through stock configuration.
Related errors
- No timeout is configured for this source.
- MessageStream never calls Ready(None)
- MessageStream never returns Ready(None)
- Messages are consumed in dedicated tasks for each partition.
- Encountered a connection-time error during runtime: {:?}
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/8f9b7db4b2be758b.
Report an issue: GitHub.