BoundaryML/baml · error · LogError

IO error

Error message

IO error: {0}

What it means

Generic IO-error variant of the logging error type in baml-log: any filesystem or stream failure encountered while writing to the configured log file (or switching log output) is wrapped in this variant, with the underlying io::Error carried in {0}. It fires from the logger's file-writing path when LOG_FILE is set, not from application logic itself.

Solutions

  1. Check the log destination path exists and is writable (permissions, disk space)
  2. Wrap logger calls to handle LogError::Io and fall back to a safe sink
  3. If piping logs, ensure the downstream reader stays alive
  4. Re-create the log file/directory if it was deleted while running

Example fix

// before
logger.write(record).unwrap();
// after
if let Err(LogError::Io(e)) = logger.write(record) {
    eprintln!("logging disabled: {e}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify log destination is writable before initializing the logger
let f = std::fs::OpenOptions::new().append(true).create(true).open(log_path)?;
assert_writable(&f.metadata()?);

Type guard

fn is_io_err(e: &LogError) -> bool { matches!(e, LogError::Io(_)) }

Try / catch

match logger.write(record) {
    Err(LogError::Io(e)) => eprintln!("log write failed: {e}"),
    Err(other) => return Err(other),
    Ok(_) => {}
}

Prevention

When it happens

Trigger: Log writes fail at the OS level: the log file/destination cannot be written (disk full, closed pipe, permission denied, flushed writer failing) when the logger emits a record.

Common situations: Logging to a file whose directory was removed or is read-only; disk quota exceeded; logging to a stdout/stderr pipe whose reader exited (broken pipe); network file systems dropping writes.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/57e6274737664c21. Report an issue: GitHub.

Appendix: source

Thrown at engine/baml-lib/baml-log/src/logger.rs:411

            max_message_length: self.max_message_length,
            running_in_lsp: self.running_in_lsp,
        }
    }
}

lazy_static! {
    /// Thread-safe configuration with runtime modification support
    static ref CONFIG: RwLock<LogConfig> = RwLock::new(LogConfig::from_env());
    static ref LOGGED_LINES: RwLock<HashSet<(Option<String>, Option<String>, Option<u32>)>> = RwLock::new(HashSet::new());
    /// Optional log file path — when set, log output goes to this file instead of stdout.
    static ref LOG_FILE: Mutex<Option<PathBuf>> = Mutex::new(None);
}

/// Error type for logging operations
#[derive(Debug, Error)]
pub enum LogError {
    /// Error writing to output
    #[error("IO error: {0}")]
    Io(#[from] io::Error),

    /// Error serializing to JSON
    #[error("JSON serialization error: {0}")]
    Json(#[from] serde_json::Error),

    /// Error acquiring lock
    #[error("Failed to acquire lock")]
    LockError,

    /// Configuration error
    #[error("Configuration error: {0}")]
    Config(String),
}

// /// JSON-serializable log entry
// #[derive(Serialize)]
// struct LogEntry<'a> {

View on GitHub (pinned to bd85ce9dee)