janhq/jan · warning · RagError::UnsupportedFileType
Unsupported file type: {0}
Error message
Unsupported file type: {0} What it means
`RagError::UnsupportedFileType(String)` is returned when a file extension or MIME signature is not in the set of formats the RAG plugin can ingest. The wrapped string identifies the offending type. It is a pure validation error — the file may be perfectly valid; the plugin simply does not know how to handle it.
Source
Thrown at src-tauri/plugins/tauri-plugin-rag/src/error.rs:8
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
- Filter files at the UI layer by allowed extensions before they reach the ingestion API.
- If the format is required, add a parser for it in the RAG plugin.
- Surface a clear user-facing message naming the unsupported type so the user can convert the file.
- For files with no extension, sniff the magic bytes to determine the real type.
Example fix
// before
let parsed = rag.ingest(&path)?;
// after - pre-filter with a clear error
const SUPPORTED: &[&str] = &["pdf", "docx", "md", "txt", "html"];
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
if !SUPPORTED.contains(&ext.as_str()) {
return Err(RagError::UnsupportedFileType(ext));
}
let parsed = rag.ingest(&path)?; Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED: &[&str] = &["pdf", "docx", "md", "txt", "html"];
fn supported_ext(path: &Path) -> Result<String, RagError> {
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("").to_lowercase();
if SUPPORTED.contains(&ext.as_str()) { Ok(ext) } else { Err(RagError::UnsupportedFileType(ext)) }
} Type guard
fn is_supported(path: &Path) -> bool {
matches!(path.extension().and_then(|e| e.to_str()).map(str::to_lowercase).as_deref(),
Some("pdf") | Some("docx") | Some("md") | Some("txt") | Some("html"))
} Try / catch
match rag.ingest(&path).await {
Ok(doc) => Ok(doc),
Err(RagError::UnsupportedFileType(t)) => {
Err(UserError::UnsupportedFile(t))
}
Err(e) => Err(e.into()),
} Prevention
- Restrict the file picker to supported extensions in the UI.
- Sniff magic bytes for files with no extension before rejecting.
- Surface the unsupported type to the user so they can convert.
When it happens
Trigger: Passing a file whose extension is not in the supported list (e.g. `.xlsx`, `.heic`, `.mp4`, `.zip`) to the ingestion API; a file with no extension; a file whose declared type does not match any registered parser.
Common situations: Users dragging arbitrary files into the ingestion UI; misconfigured MIME detection that reports an unexpected type; a backend that needs to be extended to support a new format.
Related errors
AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12).
Data as JSON: /api/errors/33d5cdb42038f80c.
Report an issue: GitHub.