{"record":{"id":"38335e1a03ca8c17","repo":"janhq/jan","slug":"io-error-0-38335e","errorCode":null,"errorMessage":"IO error: {0}","messagePattern":"IO error: (.+?)","errorType":"error_code","errorClass":"RagError::IoError","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/fad3f12a147d138388a66f0d92a02b2675f65294/src-tauri/plugins/tauri-plugin-rag/src/error.rs#L1-L21","documentation":"`RagError::IoError(String)` wraps a `std::io::Error` via the `From` impl — the wrapped string is `err.to_string()`. It fires when the RAG plugin itself hits an I/O failure while reading a source file, writing extracted text to a cache, or manipulating the vector store's files.","triggerScenarios":"Opening a file that does not exist or is unreadable; permission denied on the ingestion directory; disk full while writing the index; broken pipe or unexpected EOF mid-read on a truncated file.","commonSituations":"Wrong path passed by the user; permission issues on macOS due to App Sandbox / TCC; concurrent write contention on the index file; a file that was deleted between the UI listing it and the backend opening it.","solutions":["Inspect the wrapped message for the io::Error kind (NotFound, PermissionDenied, UnexpectedEof, etc.).","Verify the path is absolute and exists before calling ingest.","For Tauri apps, ensure the path is within scoped access (asset protocol / fs scope).","For permission errors, guide the user to grant the necessary filesystem access."],"exampleFix":"// before - From impl flattens the kind into a string\nimpl From<std::io::Error> for RagError {\n    fn from(err: std::io::Error) -> Self { RagError::IoError(err.to_string()) }\n}\n\n// after - preserve kind for caller branching\npub enum RagError {\n    IoError { kind: io::ErrorKind, message: String },\n    // ...\n}\nimpl From<std::io::Error> for RagError {\n    fn from(err: std::io::Error) -> Self {\n        RagError::IoError { kind: err.kind(), message: err.to_string() }\n    }\n}","handlingStrategy":"try-catch","validationCode":"fn readable(path: &Path) -> bool {\n    std::fs::File::open(path).is_ok()\n}","typeGuard":"null","tryCatchPattern":"match rag.ingest(&path).await {\n    Ok(doc) => Ok(doc),\n    Err(RagError::IoError(msg)) if msg.contains(\"os error 2\") => {\n        Err(UserError::NotFound(path.display().to_string()))\n    }\n    Err(RagError::IoError(msg)) if msg.contains(\"os error 13\") => {\n        Err(UserError::PermissionDenied(path.display().to_string()))\n    }\n    Err(e) => Err(e.into()),\n}","preventionTips":["Verify the path exists and is readable before opening it in the backend.","For Tauri, keep file access within the configured fs scope.","Preserve the io::Error kind through the wrapper so callers can branch on it."],"tags":["rag","io","filesystem","tauri","rust"],"backgroundTag":null,"analyzedSha":"fad3f12a147d138388a66f0d92a02b2675f65294","analyzedAt":"2026-08-12T20:33:47.516Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}