astrid-runtime/astrid · error
headless configuration error state was poisoned
Error message
headless configuration error state was poisoned
What it means
During non-interactive (`seal`) installs, configuration errors are accumulated in a shared `Mutex`-guarded `headless_errors` list and reported at the end by `run_with_elicit`. This error is thrown when the mutex is poisoned — i.e. another thread panicked while holding the lock — so the collected error list cannot be read reliably.
Solutions
- Inspect earlier logs for the panic that poisoned the mutex — that root panic is the real failure
- Retry the install; if reproducible, file a bug with the capsule manifest and command line
- Update the CLI/capsule — panics in config collection are bugs to fix at the source
Defensive patterns
Strategy: try-catch
Try / catch
match result {
Err(e) if e.to_string().contains("poisoned") => {
// Root cause is an earlier panic; re-run with backtrace and inspect logs.
eprintln!("Headless install crashed earlier (poisoned lock); re-run with RUST_BACKTRACE=1.");
}
other => other?,
} Prevention
- Treat this as a symptom: always investigate the preceding panic in logs
- Run headless installs with RUST_BACKTRACE=1 to capture root panics
- Keep astrid-cli updated; panics in config collection are upstream bugs
When it happens
Trigger: A worker thread/task that shares `headless_errors` panics while holding the lock (e.g. a bug in a config callback), then the finishing code in `run_with_elicit` calls `.lock()` on the poisoned mutex.
Common situations: A panic inside elicit/config collection tasks during headless installs (often from `.unwrap()` in a prompt formatter or malformed manifest triggering an unexpected panic); only surfaces after a prior panic, so check earlier log output.
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
- an incomplete capsule authority update exists at
- capsule source changed while archiving
- projected file changed while read
- recorder lock poisoned
- required value is missing for
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/df1d80e1daf440fb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/capsule/install_finish.rs:48
let vars = prompt.vars.clone();
let errors = std::sync::Arc::clone(&headless_errors);
handle.spawn(async move {
headless_elicit_handler(receiver, bus_for_handler, vars, errors).await;
})
} else {
handle.spawn(async move {
cli_elicit_handler(receiver, bus_for_handler).await;
})
}
});
let result = f(opts, event_bus.clone());
if let Some(task) = elicit_task {
task.abort();
}
drop(event_bus);
let errors = headless_errors
.lock()
.map_err(|_| anyhow::anyhow!("headless configuration error state was poisoned"))?;
if !errors.is_empty() {
bail!(
"non-interactive capsule configuration failed: {}",
errors.join("; ")
);
}
result
}
/// Validate install output, surface diagnostics, and persist manual install
/// configuration before returning the installed capsule identity.
pub(super) fn finish_install(
output: &InstallOutput,
home: &AstridHome,
principal: &astrid_core::PrincipalId,
prompt: &ManualInstallOptions,
) -> anyhow::Result<InstalledCapsuleOutcome> {
let batch = BATCH_MODE.load(std::sync::atomic::Ordering::Relaxed);View on GitHub (pinned to affd8760f4)