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

  1. Add a font attribute to the <text> element, e.g. font="Sans".
  2. Regenerate the file ensuring every <text> element includes font and size.
  3. 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

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.

Related errors


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)