diff --git a/codex-rs/app-server/src/request_processors/account_processor.rs b/codex-rs/app-server/src/request_processors/account_processor.rs index f0e1ebfc3d..1a01a7a7a5 100644 --- a/codex-rs/app-server/src/request_processors/account_processor.rs +++ b/codex-rs/app-server/src/request_processors/account_processor.rs @@ -193,11 +193,18 @@ impl AccountRequestProcessor { } } - async fn load_latest_config(&self) -> Result { - self.config_manager + async fn load_latest_config(&self) -> Config { + match self + .config_manager .load_latest_config(/*fallback_cwd*/ None) .await - .map_err(|err| internal_error(format!("failed to reload config: {err}"))) + { + Ok(config) => config, + Err(err) => { + tracing::warn!("failed to reload config, using startup config: {err}"); + self.config.as_ref().clone() + } + } } async fn maybe_refresh_plugin_caches_for_current_config( @@ -906,7 +913,7 @@ impl AccountRequestProcessor { // Determine whether auth is required based on the active model provider. // If a custom provider is configured with `requires_openai_auth == false`, // then no auth step is required; otherwise, default to requiring auth. - let config = self.load_latest_config().await?; + let config = self.load_latest_config().await; let requires_openai_auth = config.model_provider.requires_openai_auth; let response = if !requires_openai_auth { @@ -975,7 +982,7 @@ impl AccountRequestProcessor { self.refresh_token_if_requested(do_refresh).await; - let config = self.load_latest_config().await?; + let config = self.load_latest_config().await; let provider = create_model_provider(config.model_provider, Some(self.auth_manager.clone())); let account_state = match provider.account_state() { diff --git a/codex-rs/app-server/tests/suite/v2/account.rs b/codex-rs/app-server/tests/suite/v2/account.rs index 5f2e161919..8c03690bf3 100644 --- a/codex-rs/app-server/tests/suite/v2/account.rs +++ b/codex-rs/app-server/tests/suite/v2/account.rs @@ -2377,6 +2377,66 @@ region = "us-west-2" Ok(()) } +#[tokio::test] +async fn account_reads_use_startup_config_when_config_reload_fails() -> Result<()> { + let codex_home = TempDir::new()?; + create_config_toml( + codex_home.path(), + CreateConfigTomlParams { + model_provider_id: Some("amazon-bedrock".to_string()), + extra_provider_config: Some( + r#"[model_providers.amazon-bedrock.aws] +profile = "codex-bedrock" +region = "us-west-2" +"# + .to_string(), + ), + ..Default::default() + }, + )?; + + let mut mcp = TestAppServer::builder() + .with_codex_home(codex_home.path()) + .without_auto_env() + .build() + .await?; + timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??; + + std::fs::write(codex_home.path().join("config.toml"), "invalid = [")?; + + assert_eq!( + read_account(&mut mcp).await?, + GetAccountResponse { + account: Some(Account::AmazonBedrock { + credential_source: AmazonBedrockCredentialSource::AwsManaged, + }), + requires_openai_auth: false, + } + ); + + let request_id = mcp + .send_get_auth_status_request(GetAuthStatusParams { + include_token: Some(false), + refresh_token: Some(false), + }) + .await?; + let response = timeout( + DEFAULT_READ_TIMEOUT, + mcp.read_stream_until_response_message(RequestId::Integer(request_id)), + ) + .await??; + assert_eq!( + to_response::(response)?, + GetAuthStatusResponse { + auth_method: None, + auth_token: None, + requires_openai_auth: Some(false), + } + ); + + Ok(()) +} + #[tokio::test] async fn get_account_with_managed_bedrock_provider() -> Result<()> { let codex_home = TempDir::new()?;