{"record":{"id":"06105976eddd87a9","repo":"tonhowtf/omniget","slug":"n-o-achei-o-cat-logo-root-do-documento","errorCode":null,"errorMessage":"não achei o catálogo (/Root) do documento","messagePattern":"não achei o catálogo \\(/Root\\) do documento","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pdf_repair.rs","lineNumber":390,"sourceCode":"            let off = out.len();\n            out.extend_from_slice(format!(\"{} 0 obj\\n\", num).as_bytes());\n            out.extend_from_slice(&content);\n            out.extend_from_slice(b\"\\nendobj\\n\");\n            by_num.insert(num, (off, 0));\n            unpacked += 1;\n        }\n    }\n    tracing::debug!(\"[pdf-repair] {} objetos soltos de object stream\", unpacked);\n\n    let max = by_num.keys().copied().max().unwrap_or(0);\n    let size = max + 1;\n    let all: Vec<(u32, usize, u16)> = by_num.iter().map(|(n, (o, g))| (*n, *o, *g)).collect();\n    let trailer = match last_trailer_dict(body) {\n        Some(d) if d.contains(\"/Root\") => patch_trailer(&d, size),\n        _ => {\n            let root = find_root_ref(&out)\n                .or_else(|| find_catalog(&out, &all))\n                .ok_or_else(|| anyhow!(\"não achei o catálogo (/Root) do documento\"))?;\n            format!(\"<< /Size {} /Root {} >>\", size, root)\n        }\n    };\n\n    let xref_at = out.len();\n    out.extend_from_slice(format!(\"xref\\n0 {}\\n\", size).as_bytes());\n    out.extend_from_slice(b\"0000000000 65535 f \\n\");\n    for n in 1..size {\n        match by_num.get(&n) {\n            Some((off, gen)) => {\n                out.extend_from_slice(format!(\"{:010} {:05} n \\n\", off, gen).as_bytes())\n            }\n            None => out.extend_from_slice(b\"0000000000 65535 f \\n\"),\n        }\n    }\n    out.extend_from_slice(b\"trailer\\n\");\n    out.extend_from_slice(trailer.trim().as_bytes());\n    out.extend_from_slice(format!(\"\\nstartxref\\n{}\\n%%EOF\\n\", xref_at).as_bytes());","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf_repair.rs#L372-L408","documentation":"When rebuilding the xref table, `rebuild_xref` must emit a trailer containing a `/Root` reference to the document catalog. If the existing trailer lacks `/Root` and neither `find_root_ref` (a `2 0 R`-style ref) nor `find_catalog` (an `obj` with `/Type /Catalog`) locates the catalog, reconstruction is impossible and this error is thrown.","triggerScenarios":"Repairing a PDF whose trailer dictionary is missing or truncated and whose catalog object is absent, renumbered in an unrecognized way, or unreferenced — so `run`/`rebuild_xref` cannot determine the document root.","commonSituations":"Files cut off mid-trailer by truncation; PDFs assembled by tools that omit the trailer (linearized/exotic writers); prior failed edits that dropped or renumbered the catalog object; files recovered from disk with partially overwritten object streams.","solutions":["Search the file for `/Type /Catalog`; if found but unreferenced, the heuristic failed — check whether the object number is unusual (e.g. very large) and consider patching `find_catalog`'s matching","Verify the file is complete — a truncated tail loses both trailer and xref; re-download or re-export the source","Try recovering the catalog from incremental updates: an earlier revision of the file may contain a valid `/Root` reference","Use a third-party recovery tool (e.g. qpdf/mutool clean) to rebuild structure before this repair"],"exampleFix":"// before\nlet (bytes, objs) = rebuild_xref(&data)?;\n// after\nif !data.windows(15).any(|w| w == b\"/Type /Catalog\") {\n    eprintln!(\"no catalog object present — rebuild_xref will fail\");\n    return Ok(());\n}\nlet (bytes, objs) = rebuild_xref(&data)?;","handlingStrategy":"validation","validationCode":"fn has_catalog(data: &[u8]) -> bool {\n    data.windows(14).any(|w| w == b\"/Type /Catalog\")\n        || data.windows(5).any(|w| w == b\"/Root\")\n}\n// require has_catalog(&data) before calling rebuild_xref on trailer-damaged files","typeGuard":null,"tryCatchPattern":"match rebuild_xref(&data) {\n    Err(e) if e.to_string().contains(\"/Root\") => {\n        eprintln!(\"catalog missing — file is too damaged for xref-only repair; use a full recovery tool\");\n    }\n    other => other?,\n}","preventionTips":["Pre-scan for /Type /Catalog before offering xref repair to users","Keep original files untouched — repair into a copy so incremental revisions can be retried","Encourage re-export from the source application when the trailer is truncated","Try qpdf --recover or mutool clean as a pre-pass on badly damaged files"],"tags":["pdf","parsing","corrupt-file","rust"],"backgroundTag":"resource-not-found","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}