tinyhumansai/openhuman · error

shutdown hooks poisoned

Error message

shutdown hooks poisoned

What it means

Mutex poisoning on the global shutdown-hook registry: a panic occurred inside another thread while it held the registry's lock (during register() or run_hooks()), so subsequent lock() calls return PoisonError and this expect fires. The root cause is the earlier panic visible in logs, not the shutdown path itself.

Source

Thrown at src/core/shutdown.rs:38

/// Register a cleanup function to run on graceful shutdown.
///
/// Use this to perform necessary cleanup tasks such as stopping background
/// services, flushing caches, or closing database connections when the
/// application is shutting down.
///
/// Hooks execute sequentially in the order they were registered.
///
/// # Arguments
///
/// * `hook` - A function that returns a future. The future will be awaited
///   during the shutdown process.
pub fn register<F, Fut>(hook: F)
where
    F: Fn() -> Fut + Send + Sync + 'static,
    Fut: Future<Output = ()> + Send + 'static,
{
    let boxed: ShutdownHook = Box::new(move || Box::pin(hook()));
    HOOKS.lock().expect("shutdown hooks poisoned").push(boxed);
}

/// Run all registered hooks (called once during shutdown).
///
/// This function drains the global `HOOKS` list and awaits each hook in sequence.
async fn run_hooks() {
    let hooks: Vec<ShutdownHook> = {
        let mut guard = HOOKS.lock().expect("shutdown hooks poisoned");
        // Use mem::take to clear the hooks list and take ownership of the vector.
        std::mem::take(&mut *guard)
    };
    for hook in &hooks {
        hook().await;
    }
}

/// Returns a future that resolves when the process receives a termination
/// signal (SIGINT on all platforms, plus SIGTERM on Unix), then runs all

View on GitHub (pinned to 7491200858)

Solutions

  1. Find and fix the panic that poisoned the lock (it precedes this error in the logs)
  2. Use lock().unwrap_or_else(|e| e.into_inner()) to recover the registry if hooks are still needed
  3. Register hooks early so registration cannot race a failing hook run
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at src/core/shutdown.rs:38 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/0045b640c01e540c. Report an issue: GitHub.