aaif-goose/goose · error

Failed to unwrap provider for recording

Error message

Failed to unwrap provider for recording

What it means

After a successful recording-mode scenario, Arc::try_unwrap on the provider failed, meaning another clone of the Arc<TestProvider> was still alive when finish_recording() was attempted. drop(cli_session) ran, but some other holder (a leaked session handle, an in-flight task or subagent that captured the provider) keeps the refcount above one. This is an internal lifetime bug in the harness, not a user configuration problem.

Source

Thrown at crates/goose-cli/src/scenario_tests/scenario_runner.rs:300

                "Test replay failed for '{}' ({}) - missing recorded interaction: {}. File deleted - re-run test to record fresh data.",
                test_name, factory_name, err_msg
            ));
        }
    }

    let result = ScenarioResult {
        messages: updated_messages,
        error,
    };

    validator(&result)?;

    drop(cli_session);

    if let Some(provider) = provider_for_saving {
        if result.error.is_none() {
            Arc::try_unwrap(provider)
                .map_err(|_| anyhow::anyhow!("Failed to unwrap provider for recording"))?
                .finish_recording()?;
        }
    }

    if let Some(env) = original_env {
        restore_environment(config, &env);
    }

    Ok(())
}

fn setup_environment(config: &ProviderConfig) -> Result<HashMap<&'static str, String>> {
    let mut original_env = HashMap::new();

    for &var in config.required_env_vars {
        if let Ok(val) = std::env::var(var) {
            original_env.insert(var, val);
        }

View on GitHub (pinned to 3810898a74)

Solutions

  1. Re-run — if failure is scheduling-dependent it may pass, but treat repeats as a real leak.
  2. If developing: audit every Arc::clone of the provider (cli_session, subagents, middleware) and ensure holders are dropped before finish_recording.
  3. File a goose issue with the scenario name and provider; the recording is lost when this trips.

Example fix

// before
drop(cli_session);
Arc::try_unwrap(provider)
    .map_err(|_| anyhow::anyhow!("Failed to unwrap provider for recording"))?;

// after: drop every known holder first, then unwrap
for handle in session_handles.drain(..) {
    handle.shutdown().await;
}
drop(cli_session);
let provider = Arc::try_unwrap(provider)
    .map_err(|_| anyhow::anyhow!("provider Arc still shared: {} refs", Arc::strong_count(&provider)))?;
provider.finish_recording()?;
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = finish_recording(&provider_arc) {
    if e.to_string() == "Failed to unwrap provider for recording" {
        // internal leak: report with strong_count diagnostics; recording is lost — rerun to re-record
        eprintln!("provider Arc leak (refs={}), please open an issue", Arc::strong_count(&provider_arc));
    }
}

Prevention

When it happens

Trigger: A scenario where the CLI session or a spawned subagent/thread retains a clone of the provider Arc past the explicit drop — e.g. background futures not awaited, or session teardown paths that stash the provider elsewhere.

Common situations: New agent-loop or session features that keep provider references alive; changes in drop ordering between the legacy loop and the state machine; intermittent depending on task scheduling.

Related errors


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