t8y2/dbx · error
a batch cancellation token is always available
Error message
a batch cancellation token is always available
What it means
In upgrade_all_agent_drivers_with_registry, the code builds a batch cancellation token: either it owns one (created from begin_install_cancellation for the operation) or it receives one via batch_cancellation. The invariant is that one of the two is always Some, so .expect("a batch cancellation token is always available") panics if both are None — a programming/contract violation, not a runtime condition.
Source
Thrown at crates/dbx-core/src/agent_service.rs:804
agents.iter().filter(|agent| agent.update_available).map(|agent| agent.db_type.clone()).collect();
let total = updatable.len() as u32;
// Use the command-scoped batch token when one was registered before the
// registry fetch + blocker check, so a cancel fired during that setup is
// observed. Otherwise register a token owned by this call keyed by a fresh
// operation id so it cannot collide with another in-flight operation.
let owned_operation_id: Option<String> =
if operation_id.is_some() { None } else { Some(uuid::Uuid::new_v4().to_string()) };
let effective_operation_id: &str = owned_operation_id.as_deref().or(operation_id).unwrap_or_default();
let owned_batch: Option<Arc<AgentInstallCancellation>> = if batch_cancellation.is_some() {
None
} else {
Some(am.begin_install_cancellation(&batch_cancellation_key(effective_operation_id)).await)
};
let active_batch_arc: Arc<AgentInstallCancellation> = owned_batch
.clone()
.or_else(|| batch_cancellation.cloned())
.expect("a batch cancellation token is always available");
let active_batch: &AgentInstallCancellation = active_batch_arc.as_ref();
if active_batch.is_cancelled() {
if let Some(token) = owned_batch {
am.finish_install_cancellation(&batch_cancellation_key(effective_operation_id), &token).await;
}
return Ok(UpgradeAllAgentDriversResult { cancelled: total, ..Default::default() });
}
// Register a per-driver token for every driver in the batch, keyed by the
// batch operation id so per-driver cancels target this batch's driver even
// when the same db_type is being installed concurrently elsewhere. The
// batch token lets one click abort the whole upgrade; each driver token
// lets the user cancel a single driver while the rest continue.
let mut driver_cancellations = std::collections::HashMap::new();
for db_type in &updatable {
let key = batch_driver_cancellation_key(effective_operation_id, db_type);
let token = am.begin_install_cancellation(&key).await;
driver_cancellations.insert(db_type.clone(), token);View on GitHub (pinned to c0390bff16)
Solutions
- Ensure every call path supplies either an operation id (so owned_batch is created) or a batch_cancellation token.
- If a caller legitimately has neither, generate an operation id / call begin_install_cancellation before invoking.
- Replace the expect with explicit error handling (return a generic token via begin_install_cancellation) if the invariant may not hold.
- Add a debug_assert/test covering all public callers to keep the invariant enforced.
Example fix
// before
let owned_batch = if cancelled_all { None } else {
Some(am.begin_install_cancellation(&batch_cancellation_key(effective_operation_id)).await)
};
// after
effective_operation_id.get_or_insert_with(Uuid::new_v4);
let owned_batch = Some(am.begin_install_cancellation(&batch_cancellation_key(effective_operation_id)).await); Defensive patterns
Strategy: validation
Validate before calling
// before calling the batch upgrade API, ensure a token source exists
debug!(operation_id = ?effective_operation_id, has_batch = batch_cancellation.is_some());
assert!(effective_operation_id.is_some() || batch_cancellation.is_some(),
"batch upgrade requires an operation id or a batch cancellation token"); Type guard
fn has_batch_token(op_id: Option<&OperationId>, token: Option<&AgentInstallCancellation>) -> bool {
op_id.is_some() || token.is_some()
} Try / catch
// Rust panics are not catchable with try/catch; use catch_unwind at the boundary only
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(||
upgrade_all_agent_drivers_from(...)
));
match result {
Ok(inner) => inner,
Err(_) => Err("batch upgrade panicked: missing cancellation token".into()),
} Prevention
- Always generate an operation id when none is supplied before invoking batch upgrade.
- Centralize token creation in one wrapper instead of relying on each caller.
- Add a unit test for the None/None input combination.
- Prefer Result-returning constructors over expect for token resolution.
When it happens
Trigger: Calling upgrade_all_agent_drivers_with_registry (via upgrade_all_agent_drivers_from / _claimed, or the batch tests) with effective_operation_id = None AND batch_cancellation = None, i.e. an upgrade-all run that neither creates nor is handed a batch cancellation token.
Common situations: A refactor adds a new call site that passes no operation id and no shared batch token; tests invoke the registry upgrade path directly without going through the wrappers that always create the batch token; an operation-id plumbing bug makes effective_operation_id None in the batch path.
Related errors
- driver token registered
- a cancellation token is always available
- checked one driver
- checked one native platform
- root count checked above
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/e322d5243890e787.
Report an issue: GitHub.