Fix readline/TTY errors to propagate as quick exits instead of being silently swallowed or displayed as inline errors, ensuring the process terminates cleanly when the terminal is unavailable.
Context
When Forge runs in a non-TTY environment (e.g., piped input, CI, or other headless contexts), the readline prompt fails with an I/O error. Previously, these errors were treated identically to recoverable runtime errors — they were displayed inline and the loop continued, leading to confusing behavior or infinite error loops. This fix ensures that readline failures cause a clean, immediate exit with the error propagated to the caller.
Changes
Introduced a dedicated ReadLineError wrapper type (using thiserror) to distinguish readline/TTY failures from other runtime errors
Updated ForgeEditor::prompt to wrap I/O errors in ReadLineError so they can be identified downstream
Updated the UI error-handling loop to detect ReadLineError and return early (quick exit) instead of displaying the error inline
Added all errors to tracker and tracing before the readline type check so nothing is lost
Added a comment explaining the TTY failure behavior on the first prompt call
Key Implementation Details
The error discrimination uses error.downcast::<ReadLineError>() after logging/tracking the error. If the downcast succeeds, the error is re-returned immediately via Err(error)?, causing the entire UI task to exit. If it fails (a normal recoverable error), the existing inline display path is used. This ensures zero behavioral change for non-readline errors.
Testing
# Run crate-specific tests
cargo insta test --accept -p forge_main
# Simulate a non-TTY environment to trigger readline error pathecho"hello"| cargo run -- --help
# Verify clean exit code on TTY failureecho$?
tusharmath
changed the title
fix(ui): propagate prompt error with early exit using anyhow::Ok
fix(ui): propagate readline/TTY errors as quick exit
Mar 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix readline/TTY errors to propagate as quick exits instead of being silently swallowed or displayed as inline errors, ensuring the process terminates cleanly when the terminal is unavailable.
Context
When Forge runs in a non-TTY environment (e.g., piped input, CI, or other headless contexts), the readline prompt fails with an I/O error. Previously, these errors were treated identically to recoverable runtime errors — they were displayed inline and the loop continued, leading to confusing behavior or infinite error loops. This fix ensures that readline failures cause a clean, immediate exit with the error propagated to the caller.
Changes
Key Implementation Details
The error discrimination uses error.downcast::<ReadLineError>() after logging/tracking the error. If the downcast succeeds, the error is re-returned immediately via Err(error)?, causing the entire UI task to exit. If it fails (a normal recoverable error), the existing inline display path is used. This ensures zero behavioral change for non-readline errors.
Testing
Links