janhq/jan · warning · RagError::UnsupportedFileType

Unsupported file type

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.

Solutions

  1. Filter files at the UI layer by allowed extensions before they reach the ingestion API.
  2. If the format is required, add a parser for it in the RAG plugin.
  3. Surface a clear user-facing message naming the unsupported type so the user can convert the file.
  4. 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

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.

Appendix: 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)