{"record":{"id":"d8ee46d6d5a1f8f1","repo":"flxzt/rnote","slug":"failed-to-parse-height-attribute-of-xopppage-with","errorCode":null,"errorMessage":"failed to parse height attribute of XoppPage with node id {:?}, could not find attribute","messagePattern":"failed to parse height attribute of XoppPage with node id (.+?), could not find attribute","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/fileformats/xoppformat.rs","lineNumber":163,"sourceCode":"    pub layers: Vec<XoppLayer>,\n}\n\nimpl XmlLoadable for XoppPage {\n    fn load_from_xml(&mut self, node: Node) -> anyhow::Result<()> {\n        self.width = node\n            .attribute(\"width\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse width attribute of XoppPage for node with id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        self.height = node\n            .attribute(\"height\")\n            .ok_or_else(|| {\n                anyhow::anyhow!(\n                    \"failed to parse height attribute of XoppPage with node id {:?}, could not find attribute\",\n                    node.id()\n                )\n            })?\n            .parse::<f64>()?;\n\n        for child in node.children() {\n            match child.node_type() {\n                NodeType::Element => match child.tag_name().name() {\n                    \"background\" => {\n                        self.background.load_from_xml(child)?;\n                    }\n                    \"layer\" => {\n                        let mut new_layer = XoppLayer::default();\n                        new_layer.load_from_xml(child)?;\n                        self.layers.push(new_layer);\n                    }\n                    _ => {}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/fileformats/xoppformat.rs#L145-L181","documentation":"XoppPage::load_from_xml requires a 'height' attribute on the <page> element; when absent the loader returns this error. Width is parsed first, so this fires only for pages that have width but no height.","triggerScenarios":"load_from_xml encountering a <page> node missing 'height' — typically a hand-edited or externally generated .xopp file.","commonSituations":"Third-party tools emitting partial page definitions; users editing .xopp XML directly and deleting an attribute; malformed export from another app.","solutions":["Re-save the file in Xournal++ to restore complete page attributes","Add height=\"...\" to the <page> element matching its width's aspect","Check both width and height attributes exist together when generating xopp files","Validate the document structure before import"],"exampleFix":"// before\n<page width=\"793.7\">\n// after\n<page width=\"793.7\" height=\"1122.52\">","handlingStrategy":"validation","validationCode":"fn has_required_page_attrs(node: &roxmltree::Node) -> bool {\n    node.attributes().any(|a| a.name() == \"height\")\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = page.load_from_xml(node) {\n    if e.to_string().contains(\"height attribute\") {\n        page.height = DEFAULT_PAGE_HEIGHT; // fallback\n    } else { return Err(e); }\n}","preventionTips":["Emit width and height together when generating xopp pages","Validate required attributes with a schema check before load","Re-save externally produced files in Xournal++"],"tags":["xml-parsing","file-formats","xopp","rust"],"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"}