flxzt/rnote · error
failed to parse `font` attribute in XoppText with node id
Error message
failed to parse `font` attribute in XoppText with node id {:?}, could not find attribute What it means
Thrown by XoppText::load_from_xml when a `<text>` element in the .xopp file has no `font` attribute. rnote reads the font name string into XoppText.font and requires it to reconstruct text styling, so a missing attribute aborts parsing with this error including the node id.
Solutions
- Add a font attribute to the <text> element, e.g. font="Sans".
- Regenerate the file ensuring every <text> element includes font and size.
- Open and re-save the file in Xournal++ so required text attributes are written, then import.
Example fix
// before (file XML) <text size="12" x="10" y="20">Hello</text> // after (file XML) <text font="Sans" size="12" x="10" y="20">Hello</text>
Defensive patterns
Strategy: validation
Validate before calling
fn text_elements_have_required_attrs(xml: &str) -> Result<(), String> {
const REQ: [&str; 5] = ["font=", "size=", "x=", "y=", "color="];
for (i, chunk) in xml.split("<text").skip(1).enumerate() {
let head = chunk.split('>').next().unwrap_or("");
for r in REQ {
if !head.contains(r) {
return Err(format!("text #{i} missing attribute {}", r.trim_end_matches('=')));
}
}
}
Ok(())
} Type guard
fn text_attrs_ok(attrs: &[(&str, &str)]) -> bool {
["font", "size", "x", "y", "color"]
.iter()
.all(|req| attrs.iter().any(|(k, _)| k == req))
} Try / catch
match import_xopp(path) {
Err(e) if e.to_string().contains("attribute in XoppText") => {
eprintln!("A <text> element is missing a required attribute (font/size/x/y/color): {e:#}");
}
Err(e) => eprintln!("import failed: {e:#}"),
Ok(doc) => { /* proceed */ }
} Prevention
- Generate text elements with font, size, x, y, and color always present
- Test generators on a minimal file round-tripped through Xournal++
- Don't rely on defaults for attributes the XOPP format marks mandatory
When it happens
Trigger: Importing a .xopp file whose `<text>` element lacks `font` — e.g. files written by external scripts, hand-edited XML, or a producer assuming a default font and omitting the attribute.
Common situations: Programmatic xopp text generation omitting font; manual XML cleanup that removed the attribute; corrupted files.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse `tool` attribute in XoppStroke with node id
- failed to parse `color` attribute in XoppStroke with node id
- failed to parse `width` attribute in XoppStroke with node id
- failed to parse `size` attribute in XoppText with node id
- failed to parse `x` attribute in XoppText with node id
AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08).
Data as JSON: /api/errors/ea3729b3c1872892.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/xoppformat.rs:867
pub font: String,
/// The text size.
pub size: f64,
/// The x position of the upper left corner.
pub x: f64,
/// The y position of the upper left corner.
pub y: f64,
/// The text color.
pub color: XoppColor,
/// The text string.
pub text: String,
}
impl XmlLoadable for XoppText {
fn load_from_xml(&mut self, node: Node) -> anyhow::Result<()> {
self.font = node
.attribute("font")
.ok_or_else(|| {
anyhow::anyhow!(
"failed to parse `font` attribute in XoppText with node id {:?}, could not find attribute",
node.id()
)
})?
.to_string();
self.size = node
.attribute("size")
.ok_or_else(|| {
anyhow::anyhow!(
"failed to parse `size` attribute in XoppText with node id {:?}, could not find attribute",
node.id()
)
})?
.parse::<f64>()?;
self.x = node
.attribute("x")View on GitHub (pinned to bbc5354502)