tonhowtf/omniget · error

documento sem catálogo

Error message

documento sem catálogo: {}

What it means

After building the outline, write_outline reads the trailer's Root (catalog) reference with doc.trailer.get(b"Root").and_then(Object::as_reference); if that lookup fails the error is wrapped as "documento sem catálogo" ("document without catalog"). The catalog is required to attach the Outlines reference so PDF viewers show the bookmark tree.

Solutions

  1. Repair the PDF with qpdf (qpdf broken.pdf fixed.pdf) to rebuild a proper trailer/catalog.
  2. Re-export the PDF from the originating application.
  3. Inspect the wrapped lopdf error in the message for the exact trailer problem.
  4. Use lopdf to delete and re-add a Root catalog object before writing the outline.
Defensive patterns

Strategy: try-catch

Validate before calling

let doc = lopdf::Document::load(&opts.input)?;
if doc.trailer.get(b"Root").is_err() {
    return Err(anyhow!("{}: PDF has no catalog; repair with qpdf", opts.input));
}

Try / catch

match write_outline(&opts) {
    Err(e) if e.to_string().contains("documento sem catálogo") => {
        eprintln!("repairing input PDF and retrying");
        std::process::Command::new("qpdf").args([&opts.input, &repaired]).status()?;
        // retry with repaired file
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling write_outline on a PDF whose trailer lacks a Root entry or whose Root is not an indirect reference (e.g. heavily stripped or hand-crafted documents).

Common situations: Corrupted trailers after an interrupted download; PDFs post-processed by tools that rewrote the trailer; minimal/generated PDFs with a missing or inline Root object.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/1ef6382e0b79c7ce. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/pdf_write.rs:796

            .ok_or_else(|| anyhow!("página {} não existe", e.page))?;
        let parent = if e.level == 0 {
            None
        } else {
            parents.get(e.level as usize - 1).copied()
        };
        let bookmark = lopdf::Bookmark::new(e.title.clone(), [0.0, 0.0, 0.0], 0, page_id);
        let id = doc.add_bookmark(bookmark, parent);
        parents.truncate(e.level as usize);
        parents.push(id);
    }
    // `build_outline` monta a árvore e devolve o id, mas quem aponta para
    // ela é o catálogo — sem isto o leitor não mostra sumário nenhum.
    if let Some(outline_id) = doc.build_outline() {
        let root = doc
            .trailer
            .get(b"Root")
            .and_then(Object::as_reference)
            .map_err(|e| anyhow!("documento sem catálogo: {}", e))?;
        if let Ok(catalog) = doc.get_dictionary_mut(root) {
            catalog.set("Outlines", Object::Reference(outline_id));
            catalog.set("PageMode", Object::Name(b"UseOutlines".to_vec()));
        }
    }

    let out = out_path(&opts.input, &opts.output_dir, &opts.suffix, "-sumario")?;
    doc.save(&out).map_err(|e| anyhow!("não gravei: {}", e))?;
    Ok(WriteItem {
        input: opts.input.clone(),
        output: Some(out.to_string_lossy().to_string()),
        pages: pages.len(),
        note: format!("{} entradas", entries.len()),
        ok: true,
        error: None,
    })
}

View on GitHub (pinned to 8600b91f42)