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

  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.