{"record":{"id":"b0a57d454f1dcc8b","repo":"tonhowtf/omniget","slug":"p-gina-n-o-existe","errorCode":null,"errorMessage":"página {} não existe","messagePattern":"página (.+?) não existe","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pdf_write.rs","lineNumber":778,"sourceCode":"}\n\npub fn write_outline(opts: &OutlineOptions) -> anyhow::Result<WriteItem> {\n    let mut doc = load(&opts.input, \"\")?;\n    let pages: BTreeMap<u32, lopdf::ObjectId> = doc.get_pages();\n    if pages.is_empty() {\n        return Err(anyhow!(\"documento sem páginas\"));\n    }\n    doc.delete_outlines()\n        .map_err(|e| anyhow!(\"não limpei o sumário antigo: {}\", e))?;\n\n    let entries = normalize_levels(&opts.entries);\n    // Pilha com o id do último item de cada nível, para pendurar os filhos.\n    let mut parents: Vec<u32> = Vec::new();\n    for e in &entries {\n        let page_id = *pages\n            .get(&e.page)\n            .or_else(|| pages.values().next())\n            .ok_or_else(|| anyhow!(\"página {} não existe\", e.page))?;\n        let parent = if e.level == 0 {\n            None\n        } else {\n            parents.get(e.level as usize - 1).copied()\n        };\n        let bookmark = lopdf::Bookmark::new(e.title.clone(), [0.0, 0.0, 0.0], 0, page_id);\n        let id = doc.add_bookmark(bookmark, parent);\n        parents.truncate(e.level as usize);\n        parents.push(id);\n    }\n    // `build_outline` monta a árvore e devolve o id, mas quem aponta para\n    // ela é o catálogo — sem isto o leitor não mostra sumário nenhum.\n    if let Some(outline_id) = doc.build_outline() {\n        let root = doc\n            .trailer\n            .get(b\"Root\")\n            .and_then(Object::as_reference)\n            .map_err(|e| anyhow!(\"documento sem catálogo: {}\", e))?;","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pdf_write.rs#L760-L796","documentation":"write_outline maps each outline entry's e.page (1-based) to a page object id via pages.get(&e.page); if that page doesn't exist it falls back to the first page, and if the document has no pages at all it throws \"página {} não existe\" (\"page {} does not exist\"). Since page existence was checked earlier, this mainly fires on out-of-range page numbers combined with an edge-case page map.","triggerScenarios":"Calling write_outline with an OutlineEntry whose page number exceeds the document's page count (and the fallback lookup also fails).","commonSituations":"Hardcoded bookmark page numbers that don't match the current document; entries generated for a different revision of the PDF; off-by-one mistakes (0 vs 1-based page numbers).","solutions":["Validate every entry's page is within 1..=page_count before calling write_outline.","Clamp or adjust out-of-range entry pages in your own code before building OutlineOptions.","Regenerate the entries from the actual PDF's page list instead of hardcoding."],"exampleFix":"// before\nentries.push(Entry { page: 42, .. });\n// after\nlet page_count = lopdf::Document::load(&path)?.get_pages().len() as u32;\nlet page = entry.page.min(page_count).max(1);\nentries.push(Entry { page, .. });","handlingStrategy":"validation","validationCode":"let page_count = lopdf::Document::load(&opts.input)?.get_pages().len() as u32;\nfor e in &entries {\n    assert!((1..=page_count).contains(&e.page), \"entry page {} out of 1..{}\", e.page, page_count);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always clamp entry pages to the document's actual page count before building OutlineOptions.","Remember pages are 1-based; don't pass 0-based indices.","Regenerate outline entries whenever the source PDF changes."],"tags":["pdf","outline","validation","page-number"],"backgroundTag":"invalid-argument-value","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"}