tonhowtf/omniget · error

nenhum objeto encontrado — arquivo vazio ou cifrado

Error message

nenhum objeto encontrado — arquivo vazio ou cifrado

What it means

After locating the `%PDF-` header and cutting leading junk, `rebuild_xref` scans for objects with `scan_objects(body)`. If no `N G obj ... endobj` pairs are found, the file has a PDF header but no parseable objects, so a cross-reference table cannot be rebuilt. The message hints the file is empty or encrypted.

Solutions

  1. Try opening the file in a normal viewer — if it asks for a password, it is encrypted and this repair path is not applicable; decrypt first
  2. Check that the file is not truncated (compare against expected size / try re-downloading)
  3. Inspect the body with a hex dump for ` obj` markers; if present but unparsed, the object syntax is nonstandard
  4. If the transfer corrupted the bytes (ASCII-mode FTP, text email), retransfer in binary mode

Example fix

// before
let (bytes, objs) = rebuild_xref(&data)?;
// after
match rebuild_xref(&data) {
    Ok((bytes, objs)) => { /* repair succeeded */ }
    Err(e) if e.to_string().contains("nenhum objeto") => {
        eprintln!("file is empty or encrypted; trying password decryption first");
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: validation

Validate before calling

fn has_plaintext_objects(data: &[u8]) -> bool {
    data.windows(5).filter(|w| w == b"%PDF-")
        .next()
        .map(|_| data.windows(4).any(|w| w == b" obj "))
        .unwrap_or(false)
}

Try / catch

match rebuild_xref(&data) {
    Err(e) if e.to_string().contains("nenhum objeto") => {
        eprintln!("empty or encrypted PDF — prompt for a password or re-export");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Input where the body is entirely encrypted (no plaintext objects), a header-only stub/truncated file, or a file whose object syntax is too mangled for `scan_objects` to recognize any `obj`/`endobj` pair.

Common situations: PDFs with heavy encryption whose streams and dictionaries are not plaintext; downloads truncated to just the first bytes; files where a previous 'repair' tool stripped the body; binary content mangled by text-mode transfer (CRLF/null-byte corruption).

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/pdf_repair.rs:351

        } else {
            decoded.len()
        };
        if start <= stop && stop <= decoded.len() {
            out.push((num, decoded[start..stop].to_vec()));
        }
    }
    out
}

/// Reescreve o arquivo com uma xref nova no fim. Devolve `(bytes, objetos)`.
pub fn rebuild_xref(data: &[u8]) -> anyhow::Result<(Vec<u8>, usize)> {
    let head = find_first(data, b"%PDF-")
        .ok_or_else(|| anyhow!("não achei a assinatura %PDF- — o arquivo não parece um PDF"))?;
    // Lixo antes do cabeçalho desloca todos os offsets: corta fora.
    let body = &data[head..];
    let objects = scan_objects(body);
    if objects.is_empty() {
        return Err(anyhow!(
            "nenhum objeto encontrado — arquivo vazio ou cifrado"
        ));
    }

    let mut out = body.to_vec();
    if !out.ends_with(b"\n") {
        out.push(b'\n');
    }
    let mut by_num: std::collections::BTreeMap<u32, (usize, u16)> =
        objects.iter().map(|(n, o, g)| (*n, (*o, *g))).collect();

    // PDF 1.5+ comprime objeto dentro de objeto. Reescreve cada um solto no
    // fim do arquivo — é o que deixa a xref plana voltar a fazer sentido.
    let mut unpacked = 0usize;
    for idx in 0..objects.len() {
        let (a, b) = object_body(body, &objects, idx);
        for (num, content) in expand_object_stream(&body[a..b]) {
            if by_num.contains_key(&num) {

View on GitHub (pinned to 8600b91f42)