Conversation
tusharmath
commented
Apr 5, 2026
- chore(ISSUE_TEMPLATE): streamline bug report fields
- feat(ui): add workspace init confirmation before syncing (feat(ui): add workspace init confirmation before syncing #2822)
- feat(provider): add Google AI Studio support (chore(provider): add Google AI Studio support #2805)
- feat(auth): add OAuth authorization code + PKCE for Codex provider (feat(auth): add OAuth authorization code + PKCE for Codex provider #2790)
- chore(deps): bump the major group across 1 directory with 5 updates (chore(deps): bump the major group across 1 directory with 5 updates #2783)
- fix(bedrock): sanitize tool call IDs for Anthropic compatibility (fix(bedrock): sanitize tool call IDs for Anthropic compatibility #2837)
- feat(config): read ForgeConfig once at startup with cache
crates/forge_app/src/infra.rs
Outdated
| pub trait ConfigReaderInfra: Send + Sync { | ||
| /// Returns the full [`ForgeConfig`] for the current session. | ||
| /// | ||
| /// Reads from the in-memory cache; does not perform disk I/O on every call. | ||
| fn get_config(&self) -> ForgeConfig; | ||
| } | ||
|
|
There was a problem hiding this comment.
Completely drop ConfigInfra. We will never read config infra dynamically ever. Make sure to pass an instance of ForgeConfig in <TypeName>::new() constructor wherever required.
crates/forge_config/src/reader.rs
Outdated
| Err(e) => { | ||
| warn!(error = ?e, "Failed to read legacy config file; skipping"); | ||
| self | ||
| } |
There was a problem hiding this comment.
Revert all changes in forge_config.
crates/forge_main/src/main.rs
Outdated
| // Read and validate configuration at startup so any errors are surfaced | ||
| // immediately rather than silently falling back to defaults at runtime. | ||
| let config = ForgeConfig::read().context( | ||
| "Failed to read Forge configuration. Please check your ~/.forge/.forge.toml file.", |
There was a problem hiding this comment.
Keep context, but don't provide file path. It can change we don't want to hardcode it here. Just say .forge.toml
crates/forge_infra/src/env.rs
Outdated
| impl ConfigReaderInfra for ForgeEnvironmentInfra { | ||
| fn get_config(&self) -> ForgeConfig { | ||
| self.cached_config() | ||
| .expect("ForgeConfig cache read failed after update_environment") | ||
| } | ||
| } |
There was a problem hiding this comment.
Critical: .expect() will panic if config re-read fails after update_environment
The get_config() implementation uses .expect() on a Result<ForgeConfig> that can fail. After update_environment() invalidates the cache (line 165), the next get_config() call triggers a disk re-read via cached_config(). If that re-read fails (e.g., corrupted TOML file, permissions issue), the application will panic instead of returning an error.
Fix: Change the trait signature to return Result<ForgeConfig> and propagate the error, or handle the error gracefully:
impl ConfigReaderInfra for ForgeEnvironmentInfra {
fn get_config(&self) -> ForgeConfig {
self.cached_config()
.unwrap_or_else(|e| {
tracing::error!(error = ?e, "Failed to read config after update; using defaults");
ForgeConfig::default()
})
}
}Alternatively, make the trait method fallible:
fn get_config(&self) -> anyhow::Result<ForgeConfig>| impl ConfigReaderInfra for ForgeEnvironmentInfra { | |
| fn get_config(&self) -> ForgeConfig { | |
| self.cached_config() | |
| .expect("ForgeConfig cache read failed after update_environment") | |
| } | |
| } | |
| impl ConfigReaderInfra for ForgeEnvironmentInfra { | |
| fn get_config(&self) -> ForgeConfig { | |
| self.cached_config() | |
| .unwrap_or_else(|e| { | |
| tracing::error!(error = ?e, "Failed to read config after update; using defaults"); | |
| ForgeConfig::default() | |
| }) | |
| } | |
| } | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
abe22c8 to
0eb1a98
Compare
| // Handle creating a new conversation | ||
| async fn on_new(&mut self) -> Result<()> { | ||
| self.api = Arc::new((self.new_api)()); | ||
| let config = forge_config::ForgeConfig::read().unwrap_or_default(); |
There was a problem hiding this comment.
Defeats the purpose of the PR by silently falling back to defaults on config read errors.
The line reads:
let config = forge_config::ForgeConfig::read().unwrap_or_default();This silently swallows configuration errors using unwrap_or_default(), which is exactly the behavior this PR is supposed to fix. If the config file is corrupt when the user runs /new, it will silently use default values (all zeros) instead of surfacing the error to the user.
Fix:
let config = forge_config::ForgeConfig::read()
.context("Failed to read configuration for new conversation")?;This propagates the error so the user sees a clear message instead of silently broken behavior with default config values.
| let config = forge_config::ForgeConfig::read().unwrap_or_default(); | |
| let config = forge_config::ForgeConfig::read().context("Failed to read configuration for new conversation")?; |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.