{"record":{"id":"3fa3be1116f803ea","repo":"janhq/jan","slug":"ioerror","errorCode":"IoError","errorMessage":"IO error: {0}","messagePattern":"IO error: (.+?)","errorType":"error_code","errorClass":"RagError","httpStatus":null,"severity":"error","filePath":"src-tauri/plugins/tauri-plugin-rag/src/error.rs","lineNumber":11,"sourceCode":"use serde::{Deserialize, Serialize};\n\n#[derive(Debug, thiserror::Error, Serialize, Deserialize)]\npub enum RagError {\n    #[error(\"Failed to parse document: {0}\")]\n    ParseError(String),\n\n    #[error(\"Unsupported file type: {0}\")]\n    UnsupportedFileType(String),\n\n    #[error(\"IO error: {0}\")]\n    IoError(String),\n}\n\nimpl From<std::io::Error> for RagError {\n    fn from(err: std::io::Error) -> Self {\n        RagError::IoError(err.to_string())\n    }\n}\n\n","sourceCodeStart":1,"sourceCodeEnd":21,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/src-tauri/plugins/tauri-plugin-rag/src/error.rs#L1-L21","documentation":"RagError::IoError wraps a std::io::Error as a string when filesystem operations fail during RAG ingestion or retrieval (displayed as \"IO error: {0}\"). Via the provided From impl, any std::io::Error from reading files or accessing paths is converted automatically. It indicates OS-level IO trouble, not document parsing or format issues.","triggerScenarios":"Ingesting a file that doesn't exist, lacks read permission, or was deleted mid-operation; failing to create/write index or cache directories used by the RAG plugin.","commonSituations":"Moved or renamed files between selection and ingestion; permission-restricted folders; missing index directory on first run; network mounts dropped mid-read.","solutions":["Read the wrapped message to identify the exact OS error (NotFound vs PermissionDenied).","Verify the file path exists and is readable before ingestion (fs::metadata check).","Ensure the plugin's index/storage directories exist and are writable.","Handle transient failures (network drives) with a retry around ingestion."],"exampleFix":"// before\nlet text = read_document(path)?;\n\n// after\nlet text = read_document(path).map_err(|e| match e {\n    RagError::IoError(msg) => {\n        eprintln!(\"cannot read {path:?}: {msg}\");\n        e\n    }\n    other => other,\n})?;","handlingStrategy":"validation","validationCode":"// Rust: verify the file is readable before RAG operations\nfn readable(path: &Path) -> bool {\n    std::fs::File::open(path).is_ok()\n}","typeGuard":"fn as_io_error(err: &RagError) -> Option<&str> {\n    match err { RagError::IoError(m) => Some(m), _ => None }\n}","tryCatchPattern":"match rag.ingest(path) {\n    Err(RagError::IoError(msg)) => {\n        log::warn!(\"io problem with {path:?}: {msg}\");\n        retry_with_backoff(|| rag.ingest(path));\n    }\n    other => other?,\n}","preventionTips":["Check file existence and permissions before ingestion.","Create the plugin's index/storage directories at startup.","Retry transient IO failures (network mounts) with backoff.","Watch for files disappearing between selection and ingestion in UI flows."],"tags":["io","rag","rust"],"backgroundTag":"file-read-failed","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}