aaif-goose/goose · error · anyhow::Error

Failed to acquire registry lock

Error message

Failed to acquire registry lock

What it means

The local-models registry is guarded by a std Mutex. `lock()` returns Err when the mutex is poisoned — meaning some thread panicked while holding it — and the `goose local-models list` handler maps that poisoned-lock error to this message instead of listing models.

Source

Thrown at crates/goose-cli/src/cli.rs:2150

            println!(
                "\nDownloaded {} ({}). Registering...",
                model_id,
                if total_size > 0 {
                    format!("{:.1}GB", total_size as f64 / (1024.0 * 1024.0 * 1024.0))
                } else {
                    "unknown size".to_string()
                }
            );

            let model_id = hf_models::register_resolved_model(resolved, &spec)?;

            println!("Registered: {}", model_id);
        }
        LocalModelsCommand::List => {
            let registry = get_registry()
                .lock()
                .map_err(|_| anyhow::anyhow!("Failed to acquire registry lock"))?;
            let models = registry.list_models();

            if models.is_empty() {
                println!("No local models downloaded.");
                return Ok(());
            }

            println!(
                "{:<50} {:<10} {:<12} Downloaded",
                "ID", "Backend", "Variant"
            );
            println!("{}", "-".repeat(88));
            for m in models {
                println!(
                    "{:<50} {:<10} {:<12} {}",
                    m.id,
                    m.backend_id.as_deref().unwrap_or("llamacpp"),
                    m.quantization,

View on GitHub (pinned to 3810898a74)

Solutions

  1. Re-run the command — a fresh process gets a fresh, un-poisoned mutex
  2. Avoid running multiple goose commands that touch the local-models registry simultaneously
  3. If it recurs, capture the original panic message from logs (the poison's root cause) and report it upstream
  4. As a last resort, reset local model registry state and re-register the models
Defensive patterns

Strategy: retry

Try / catch

# Rust: recover from a poisoned lock instead of aborting
match get_registry().lock() {
    Ok(reg) => { let _ = reg.list_models(); }
    Err(poisoned) => {
        let reg = poisoned.into_inner(); // registry state is still inspectable
        let _ = reg.list_models();
    }
}

Prevention

When it happens

Trigger: Running `goose local-models list` in a process where an earlier panic occurred on a thread holding the registry mutex, e.g. a model registration or download step that panicked mid-write.

Common situations: A crashed/interrupted `goose local-models download` within the same invocation; registry persistence panics; same-process concurrent access to the registry.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/737e4b95b54dbf15. Report an issue: GitHub.