{"record":{"id":"cf3fafe3ca1f0d65","repo":"flxzt/rnote","slug":"failed-to-parse-bottom-attribute-in-xopptext-wit","errorCode":null,"errorMessage":"failed to parse `bottom` attribute in XoppText with node id {:?}, could not find attribute","messagePattern":"failed to parse `bottom` 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":990,"sourceCode":"            })?\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\n        self.bottom = node\n            .attribute(\"bottom\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse `bottom` attribute in XoppText with node id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        // Data\n        if let Some(data) = node.text() {\n            self.data = data\n                .trim_start_matches([' ', '\\n'])\n                .trim_end_matches([' ', '\\n'])\n                .to_string();\n        }\n\n        Ok(())\n    }\n}\n","sourceCodeStart":972,"sourceCodeEnd":1008,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/fileformats/xoppformat.rs#L972-L1008","documentation":"Thrown when a `<text>` element in a .xopp file has no `bottom` attribute while parsing into XoppText. As with the other bounds errors, the parser refuses text elements without a complete bounding rectangle.","triggerScenarios":"Importing a .xopp file whose `<text>` node lacks a `bottom` XML attribute.","commonSituations":"Programmatically generated or hand-edited files missing the bottom coordinate; truncated documents; files from incompatible exporters.","solutions":["Re-save the file with Xournal++ to regenerate all bounds attributes.","Add `bottom=\"...\"` to the `<text>` node with the id shown in the error.","Correct the generating tool so it emits all four bounds attributes.","Pre-validate the xopp XML before import and report the specific missing attribute."],"exampleFix":"// before\n<text top=\"100.0\" left=\"50.0\" right=\"200.0\">...</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(\"`bottom`\") => {\n        eprintln!(\".xopp text node missing 'bottom' attribute: {e}\");\n    }\n}","preventionTips":["Check generator output includes top/left/right/bottom on every <text>.","Pre-validate the document before import.","Re-save corrupted files from Xournal++."],"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-16T09:17:16.951Z"}