From 151293413802a861da066239739ccd5976f97de7 Mon Sep 17 00:00:00 2001 From: nuthalapativarun Date: Tue, 16 Jun 2026 11:48:08 -0700 Subject: [PATCH] fix: fall back to default provider when resuming session with unavailable provider (#9547) Signed-off-by: Varun Nuthalapati Co-authored-by: Claude Sonnet 4.6 --- crates/goose-cli/src/session/builder.rs | 71 ++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/crates/goose-cli/src/session/builder.rs b/crates/goose-cli/src/session/builder.rs index a01395208..4ffa84424 100644 --- a/crates/goose-cli/src/session/builder.rs +++ b/crates/goose-cli/src/session/builder.rs @@ -531,14 +531,66 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession { } }; - let new_provider = match create( + let (new_provider, effective_provider_name, effective_model_name) = match create( &resolved.provider_name, - resolved.model_config, + resolved.model_config.clone(), extensions_for_provider.clone(), ) .await { - Ok(provider) => provider, + Ok(provider) => ( + provider, + resolved.provider_name.clone(), + resolved.model_name.clone(), + ), + Err(e) + if session_config.resume + && session_config.provider.is_none() + && is_provider_unavailable_error(&e) => + { + let fallback_provider = config.get_goose_provider().unwrap_or_else(|_| { + output::render_error("No provider configured. Run 'goose configure' first."); + process::exit(1); + }); + let fallback_model = config.get_goose_model().unwrap_or_else(|_| { + output::render_error("No model configured. Run 'goose configure' first."); + process::exit(1); + }); + eprintln!( + "{}", + style(format!( + "Warning: Could not create the session's original provider '{}' ({}). \ + Falling back to the default provider '{}'.", + resolved.provider_name, e, fallback_provider + )) + .yellow() + ); + let fallback_model_config = goose::model::ModelConfig::new(&fallback_model) + .unwrap_or_else(|e| { + output::render_error(&format!("Failed to create model configuration: {}", e)); + process::exit(1); + }) + .with_canonical_limits(&fallback_provider); + match create( + &fallback_provider, + fallback_model_config, + extensions_for_provider.clone(), + ) + .await + { + Ok(provider) => (provider, fallback_provider, fallback_model), + Err(e2) => { + output::render_error(&format!( + "Error {}.\n\ + Please check your system keychain and run 'goose configure' again.\n\ + If your system is unable to use the keyring, please try setting secret key(s) via environment variables.\n\ + For more info, see: https://goose-docs.ai/docs/troubleshooting/#keychainkeyring-errors", + e2 + )); + process::exit(1); + } + } + } Err(e) => { output::render_error(&format!( "Error {}.\n\ @@ -550,7 +602,7 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession { process::exit(1); } }; - tracing::info!("🤖 Using model: {}", resolved.model_name); + tracing::info!("🤖 Using model: {}", effective_model_name); agent .update_provider(new_provider, &session_id) @@ -613,14 +665,21 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession { if !session_config.quiet { output::display_session_info( session_config.resume, - &resolved.provider_name, - &resolved.model_name, + &effective_provider_name, + &effective_model_name, &Some(session_id), ); } session } +fn is_provider_unavailable_error(e: &anyhow::Error) -> bool { + let msg = e.to_string(); + msg.contains("is not set") + || msg.contains("not configured") + || msg.contains("Configuration value not found") +} + #[cfg(test)] mod tests { use super::*;