janhq/jan · warning · RagError::ParseError

Failed to parse document: {0}

Error message

Failed to parse document: {0}

What it means

`RagError::ParseError(String)` is returned when a document fails to parse during RAG ingestion. The wrapped string describes the specific parser failure (PDF, DOCX, Markdown, etc.). It is the catch-all for any content-extraction problem that is not an I/O error or an unsupported file type.

Source

Thrown at src-tauri/plugins/tauri-plugin-rag/src/error.rs:5

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. Read the wrapped string — it carries the parser-specific message (PDF parse error, encoding error, etc.).
  2. For PDFs, confirm the file is not encrypted; if so, decrypt or skip it.
  3. Re-open the file in its native application to confirm it is not corrupt.
  4. If the file is legitimately unparseable, log it and continue ingestion of remaining documents rather than aborting the batch.

Example fix

// before
let text = parse_pdf(&bytes)?;

// after - per-file error isolation during batch ingest
let text = match parse_pdf(&bytes) {
    Ok(t) => t,
    Err(e) => {
        tracing::warn!("skipping unparseable file {}: {e}", path.display());
        continue;
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

fn looks_parseable(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"))
}

Type guard

null

Try / catch

match rag.ingest(&path).await {
    Ok(doc) => Ok(doc),
    Err(RagError::ParseError(msg)) => {
        tracing::warn!("skipping unparseable file {}: {msg}", path.display());
        continue;
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Feeding a corrupt or password-protected PDF to the PDF parser; a malformed DOCX/HTML structure the parser cannot walk; a Markdown file with broken encoding; any document whose bytes do not match the structure the chosen parser expects.

Common situations: Password-protected or DRMed PDFs; partially downloaded documents; scanned PDFs where text extraction yields nothing useful; documents produced by tools that emit non-standard markup; very large documents that hit a parser-internal limit.

Understand the failure class

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/a32e35365c18b208. Report an issue: GitHub.