vectordotdev/vector · error
paired task no longer holding wait trigger
Error message
paired task no longer holding wait trigger
What it means
WaitHandle::wait awaits a oneshot receiver whose sender ('trigger') is held by the paired coordinated task. rx.await returning Err means the sender was dropped without firing — the paired task died or was torn down while this handle was still waiting — so the wait can never be satisfied and the code panics deliberately.
Solutions
- Find why the paired task died: check its JoinHandle/panic output and crash_rx messages from the topology.
- Ensure the task holding the WaitTrigger is spawned before calling wait() and outlives the wait.
- Check WaitHandle isn't awaited after the TaskCoordinator transitioned past its phase and dropped triggers.
Defensive patterns
Strategy: try-catch
Try / catch
match rx.await {
Ok(()) => {},
Err(_) => panic!("paired task dropped its wait trigger without firing"),
} Prevention
- Spawn the task that holds the WaitTrigger before awaiting the handle.
- Check the paired task's JoinHandle/panic output when wait never resolves.
- Don't drop the TaskCoordinator while handles are still waiting.
When it happens
Trigger: Awaiting a WaitHandle whose paired task (topology, input HTTP server, gRPC server, telemetry driver) panicked, returned early, or never got spawned, so the WaitTrigger it held was dropped; also awaiting a trigger after TaskCoordinator shutdown was already dropped.
Common situations: A component topology crashes during validation so the 'started'/'completed' trigger never fires; a test forgets to spawn the task that holds the trigger; teardown races in run_validation where the coordinator drops triggers before wait() is polled.
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
- Drain deadline received after completion.
- event forward rx should not close first
- file server exited with an error
- node exists
- Partition assignment received after completion.
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/35f7977c0a60b2ae.
Report an issue: GitHub.
Appendix: source
Thrown at src/components/validation/sync.rs:145
(trigger, handle)
}
/// Triggers the wait handle to wake up.
pub fn trigger(self) {
// We don't care if our trigger is actually received, because the receiver side may
// intentionally not be used i.e. if the code is generic in a way where only some codepaths
// wait to be triggered and others don't, but the trigger must always be called regardless.
_ = self.tx.send(());
}
}
impl WaitHandle {
/// Waits until triggered.
pub async fn wait(&mut self) {
match self.rx.as_mut() {
Some(rx) => rx
.await
.expect("paired task no longer holding wait trigger"),
None => panic!("tried to await wait trigger signal but has already been received"),
}
// If we're here, we've successfully received the signal, so we consume the
// receiver, as it cannot be used/polled again.
self.rx.take();
}
}
pub struct Configuring {
tasks_started: WaitGroup,
tasks_completed: WaitGroup,
shutdown_triggers: Mutex<Vec<WaitTrigger>>,
}
pub struct Started {
tasks_completed: Option<WaitGroup>,
shutdown_triggers: Vec<WaitTrigger>,View on GitHub (pinned to bdb87aeaa4)