Hmbown/CodeWhale · warning · BackgroundSupervisorFailure::Disconnected
background hook supervisor is unavailable
Error message
background hook supervisor is unavailable
What it means
A background hook could not be submitted because the background hook supervisor itself is unavailable — the submission channel is disconnected (supervisor dropped, shut down, or not started). Like the queue-full case, the failure is captured in the hook result's error field instead of crashing the executor.
Solutions
- Restart the session/application so the hook supervisor is re-spawned.
- Check logs for the supervisor's crash cause (panic, startup failure) and fix it.
- If this occurs during shutdown, treat the lost hook as expected and move on.
- Verify hook supervisor initialization in configuration and that startup errors are not silently skipped.
Defensive patterns
Strategy: fallback
Try / catch
let result = run_hook_background(cmd);
if !result.success && result.error == Some("background hook supervisor is unavailable".into()) {
log::error("hook supervisor down; running hook inline");
run_hook_synchronously(cmd);
} Prevention
- Ensure the hook supervisor is initialized before any tool execution begins.
- Guard supervisor tasks against panics so one bad hook cannot kill the channel.
- During shutdown, drain or skip background hooks explicitly.
When it happens
Trigger: Submitting a background hook when BackgroundSupervisorFailure::Disconnected is returned: the supervisor's channel send fails because the receiver side is gone (supervisor task ended or was never spawned).
Common situations: Supervisor task crashed earlier (panic in a hook runner); app shutdown racing with a final hook execution; supervisor never initialized due to an earlier startup error; hot-reload of configuration tearing down and not restoring the supervisor.
Related errors
- background hook supervisor queue is full
- engine event channel closed before turn
- Failed to start turn: engine operation channel closed
- hook helper did not finish within its timeout
- MCP connection ' ' was cancelled
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/7e294643a63247f6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/hooks/executor.rs:2458
plugin_authority: hook.plugin_authority.clone(),
project_authority: hook.project_authority.clone(),
});
// The result describes the bounded submission, not the run: no caller
// can mistake "queued" for "exited 0".
HookResult {
name: hook.name.clone(),
background: true,
strict: false,
success: submission.is_ok(),
exit_code: None,
stdout: String::new(),
stderr: String::new(),
duration: started.elapsed(),
error: submission.err().map(|failure| match failure {
BackgroundSupervisorFailure::Full => {
"background hook supervisor queue is full".to_string()
}
BackgroundSupervisorFailure::Disconnected => {
"background hook supervisor is unavailable".to_string()
}
}),
}
}
/// The timeout actually applied to a hook, foreground or background.
///
/// `[hooks].default_timeout_secs` *replaces* the per-hook value when set;
/// that is the shipped behavior and is documented as such in
/// `docs/HOOKS.md`.
fn effective_timeout_secs(&self, hook: &Hook) -> u64 {
self.config.effective_timeout_secs(hook)
}
}
/// Classify a tool call for `condition = { type = "tool_category", … }`.View on GitHub (pinned to 73e0f67d83)