janhq/jan · error · RagError::IoError
IO error: {0}
Error message
IO error: {0} What it means
`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.
Source
Thrown at src-tauri/plugins/tauri-plugin-rag/src/error.rs:11
use serde::{Deserialize, Serialize};
#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
pub enum RagError {
#[error("Failed to parse document: {0}")]
ParseError(String),
#[error("Unsupported file type: {0}")]
UnsupportedFileType(String),
#[error("IO error: {0}")]
IoError(String),
}
impl From<std::io::Error> for RagError {
fn from(err: std::io::Error) -> Self {
RagError::IoError(err.to_string())
}
}
View on GitHub (pinned to fad3f12a14)
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.
Example fix
// before - From impl flattens the kind into a string
impl From<std::io::Error> for RagError {
fn from(err: std::io::Error) -> Self { RagError::IoError(err.to_string()) }
}
// after - preserve kind for caller branching
pub enum RagError {
IoError { kind: io::ErrorKind, message: String },
// ...
}
impl From<std::io::Error> for RagError {
fn from(err: std::io::Error) -> Self {
RagError::IoError { kind: err.kind(), message: err.to_string() }
}
} Defensive patterns
Strategy: try-catch
Validate before calling
fn readable(path: &Path) -> bool {
std::fs::File::open(path).is_ok()
} Type guard
null
Try / catch
match rag.ingest(&path).await {
Ok(doc) => Ok(doc),
Err(RagError::IoError(msg)) if msg.contains("os error 2") => {
Err(UserError::NotFound(path.display().to_string()))
}
Err(RagError::IoError(msg)) if msg.contains("os error 13") => {
Err(UserError::PermissionDenied(path.display().to_string()))
}
Err(e) => Err(e.into()),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- IO error: {0}
- IO error: {0}
- Failed to parse document: {0}
- Unsupported file type: {0}
- Failed to decompress archive: ${String(e)}
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/38335e1a03ca8c17.
Report an issue: GitHub.