{"record":{"id":"57e6274737664c21","repo":"BoundaryML/baml","slug":"io-error-0","errorCode":null,"errorMessage":"IO error: {0}","messagePattern":"IO error: (.+?)","errorType":"exception","errorClass":"LogError","httpStatus":null,"severity":"error","filePath":"engine/baml-lib/baml-log/src/logger.rs","lineNumber":411,"sourceCode":"            max_message_length: self.max_message_length,\n            running_in_lsp: self.running_in_lsp,\n        }\n    }\n}\n\nlazy_static! {\n    /// Thread-safe configuration with runtime modification support\n    static ref CONFIG: RwLock<LogConfig> = RwLock::new(LogConfig::from_env());\n    static ref LOGGED_LINES: RwLock<HashSet<(Option<String>, Option<String>, Option<u32>)>> = RwLock::new(HashSet::new());\n    /// Optional log file path — when set, log output goes to this file instead of stdout.\n    static ref LOG_FILE: Mutex<Option<PathBuf>> = Mutex::new(None);\n}\n\n/// Error type for logging operations\n#[derive(Debug, Error)]\npub enum LogError {\n    /// Error writing to output\n    #[error(\"IO error: {0}\")]\n    Io(#[from] io::Error),\n\n    /// Error serializing to JSON\n    #[error(\"JSON serialization error: {0}\")]\n    Json(#[from] serde_json::Error),\n\n    /// Error acquiring lock\n    #[error(\"Failed to acquire lock\")]\n    LockError,\n\n    /// Configuration error\n    #[error(\"Configuration error: {0}\")]\n    Config(String),\n}\n\n// /// JSON-serializable log entry\n// #[derive(Serialize)]\n// struct LogEntry<'a> {","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/baml-log/src/logger.rs#L393-L429","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the log destination path exists and is writable (permissions, disk space)","Wrap logger calls to handle LogError::Io and fall back to a safe sink","If piping logs, ensure the downstream reader stays alive","Re-create the log file/directory if it was deleted while running"],"exampleFix":"// before\nlogger.write(record).unwrap();\n// after\nif let Err(LogError::Io(e)) = logger.write(record) {\n    eprintln!(\"logging disabled: {e}\");\n}","handlingStrategy":"try-catch","validationCode":"// Verify log destination is writable before initializing the logger\nlet f = std::fs::OpenOptions::new().append(true).create(true).open(log_path)?;\nassert_writable(&f.metadata()?);","typeGuard":"fn is_io_err(e: &LogError) -> bool { matches!(e, LogError::Io(_)) }","tryCatchPattern":"match logger.write(record) {\n    Err(LogError::Io(e)) => eprintln!(\"log write failed: {e}\"),\n    Err(other) => return Err(other),\n    Ok(_) => {}\n}","preventionTips":["Monitor disk space and permissions for log directories","Avoid piping logs to short-lived readers","Handle LogError::Io explicitly instead of unwrapping"],"tags":["io","logging","filesystem","write"],"backgroundTag":"file-write-failed","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}