{"record":{"id":"dc419592efa4f24b","repo":"flxzt/rnote","slug":"failed-to-parse-top-attribute-in-xopptext-with-n","errorCode":null,"errorMessage":"failed to parse `top` attribute in XoppText with node id {:?}, could not find attribute","messagePattern":"failed to parse `top` attribute in XoppText with node id (.+?), could not find attribute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/fileformats/xoppformat.rs","lineNumber":968,"sourceCode":"\nimpl XmlLoadable for XoppImage {\n    fn load_from_xml(&mut self, node: Node) -> anyhow::Result<()> {\n        // Left\n        self.left = node\n            .attribute(\"left\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse `left` attribute in XoppText with node id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        // Top\n        self.top = node\n            .attribute(\"top\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse `top` attribute in XoppText with node id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        // Right\n        self.right = node\n            .attribute(\"right\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse `right` attribute in XoppText with node id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        // Bottom","sourceCodeStart":950,"sourceCodeEnd":986,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/fileformats/xoppformat.rs#L950-L986","documentation":"Thrown when a `<text>` element in a Xournal++ (.xopp) file has no `top` attribute while its coordinate bounds are being parsed into XoppText. The xopp parser requires every text element to carry explicit top/left/right/bottom bounds; a missing attribute is treated as a corrupt or incomplete document.","triggerScenarios":"Parsing a .xopp file whose `<text>` node lacks a `top` XML attribute; calling the XoppFile format loader on a hand-edited or truncated file.","commonSituations":"Hand-edited or programmatically generated .xopp files missing bounds attributes; files produced by third-party tools that only emit partial coordinates; truncated/corrupted downloads.","solutions":["Open the .xopp file in Xournal++ and re-save it so all required attributes are written.","Add a `top=\"...\"` attribute to the offending `<text>` node (find the node id from the error message).","Check where the file was generated; fix the generator to emit all four bounds attributes.","Wrap the import in error handling and surface a 'corrupt xopp file' message to the user."],"exampleFix":"// before (hand-edited xopp)\n<text>...</text>\n// after\n<text top=\"100.0\" left=\"50.0\" right=\"200.0\" bottom=\"150.0\">...</text>","handlingStrategy":"validation","validationCode":"// rust\nfn text_node_has_bounds(node: &roxmltree::Node) -> bool {\n    [\"top\", \"left\", \"right\", \"bottom\"].iter().all(|a| node.attribute(a).is_some())\n}","typeGuard":"fn get_f64_attr(node: &roxmltree::Node, name: &str) -> Option<f64> {\n    node.attribute(name).and_then(|v| v.parse::<f64>().ok())\n}","tryCatchPattern":"match xopp_file.parse() {\n    Ok(doc) => doc,\n    Err(e) if e.to_string().contains(\"could not find attribute\") => {\n        eprintln!(\"corrupt .xopp file, missing bounds attribute: {e}\");\n        // offer re-save / recovery path\n    }\n}","preventionTips":["Never hand-edit .xopp files; re-save from Xournal++ instead.","Validate generated files against all four bounds attributes before importing.","Fail fast with the node id in your own pre-parser."],"tags":["xml","parsing","file-format"],"backgroundTag":"missing-required-argument","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}