bug: Fix silent failures in file I/O operations #211

Closed
opened 2026-01-09 04:42:53 +00:00 by navicore · 1 comment
navicore commented 2026-01-09 04:42:53 +00:00 (Migrated from github.com)

Problem

File I/O operations silently swallow errors using .unwrap_or_default(), hiding failures from users and making debugging difficult.

Example from crates/repl/src/app.rs (lines 156-162):

let content = if !path.exists() {
    // ... create new file
} else {
    fs::read_to_string(&path).unwrap_or_default()  // SILENT FAILURE!
};

If the file exists but cannot be read (permissions, corruption, etc.), this returns an empty string instead of reporting the error.

Impact

  • Users lose data without knowing why
  • Debugging becomes difficult ("why is my session empty?")
  • Corruption or permission issues go unnoticed
  • Violates principle of least surprise

Affected Locations

  1. crates/repl/src/app.rs:161 - Session file reading
  2. Other potential locations with .unwrap_or_default() on I/O operations

Proposed Solution

For recoverable errors (display warning, continue):

let content = match fs::read_to_string(&path) {
    Ok(c) => c,
    Err(e) => {
        eprintln!("Warning: Could not read session file: {}", e);
        String::new()  // Start fresh, but user knows why
    }
};

For critical errors (propagate):

fn load_session(&mut self) -> Result<(), SessionError> {
    let content = fs::read_to_string(&self.session_file)
        .map_err(|e| SessionError::ReadFailed(e))?;
    // ...
}

Acceptance Criteria

  • Audit all .unwrap_or_default() calls on I/O operations
  • Replace with explicit error handling (warning or propagation)
  • Users see meaningful messages when files cannot be read
  • Add tests for I/O error conditions

Labels

bug, ux, medium-priority

## Problem File I/O operations silently swallow errors using `.unwrap_or_default()`, hiding failures from users and making debugging difficult. ### Example from `crates/repl/src/app.rs` (lines 156-162): ```rust let content = if !path.exists() { // ... create new file } else { fs::read_to_string(&path).unwrap_or_default() // SILENT FAILURE! }; ``` If the file exists but cannot be read (permissions, corruption, etc.), this returns an empty string instead of reporting the error. ## Impact - Users lose data without knowing why - Debugging becomes difficult ("why is my session empty?") - Corruption or permission issues go unnoticed - Violates principle of least surprise ## Affected Locations 1. `crates/repl/src/app.rs:161` - Session file reading 2. Other potential locations with `.unwrap_or_default()` on I/O operations ## Proposed Solution ### For recoverable errors (display warning, continue): ```rust let content = match fs::read_to_string(&path) { Ok(c) => c, Err(e) => { eprintln!("Warning: Could not read session file: {}", e); String::new() // Start fresh, but user knows why } }; ``` ### For critical errors (propagate): ```rust fn load_session(&mut self) -> Result<(), SessionError> { let content = fs::read_to_string(&self.session_file) .map_err(|e| SessionError::ReadFailed(e))?; // ... } ``` ## Acceptance Criteria - [ ] Audit all `.unwrap_or_default()` calls on I/O operations - [ ] Replace with explicit error handling (warning or propagation) - [ ] Users see meaningful messages when files cannot be read - [ ] Add tests for I/O error conditions ## Labels bug, ux, medium-priority
navicore commented 2026-01-10 17:53:13 +00:00 (Migrated from github.com)
https://github.com/navicore/patch-seq/pull/224
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-seq#211
No description provided.