flxzt/rnote · error

failed to parse `left` attribute in XoppText with node id

Error message

failed to parse `left` attribute in XoppText with node id {:?}, could not find attribute

What it means

Thrown by XoppImage::load_from_xml when an `<image>` element has no `left` attribute. The left offset is parsed as f64 to position the image; its absence aborts parsing. Note the message says "XoppText" — it is a copy-paste mislabel in rnote's source; the actual element being parsed is XoppImage.

Solutions

  1. Add a left attribute to the <image> element, e.g. left="0.0" (and ensure right/top/bottom are also present).
  2. Regenerate the file with all four position attributes on every <image> element.
  3. Open and re-save the file in Xournal++ to write canonical image attributes, then re-import.

Example fix

// before (file XML)
<image right="200" top="0" bottom="100">...</image>
// after (file XML)
<image left="0" right="200" top="0" bottom="100">...</image>
Defensive patterns

Strategy: validation

Validate before calling

fn image_has_position_attrs(xml: &str) -> Result<(), String> {
    const REQ: [&str; 4] = ["left=", "right=", "top=", "bottom="];
    for (i, chunk) in xml.split("<image").skip(1).enumerate() {
        let head = chunk.split('>').next().unwrap_or("");
        for r in REQ {
            if !head.contains(r) {
                return Err(format!("image #{i} missing attribute {}", r.trim_end_matches('=')));
            }
        }
    }
    Ok(())
}

Type guard

fn image_attrs_ok(attrs: &[(&str, &str)]) -> bool {
    ["left", "right", "top", "bottom"]
        .iter()
        .all(|req| attrs.iter().any(|(k, _)| k == req))
}

Try / catch

match import_xopp(path) {
    Err(e) if e.to_string().contains("`left` attribute in XoppText") => {
        // note: message mislabels XoppImage as XoppText; still fix the <image> element
        eprintln!("An <image> element is missing position attributes (left/right/top/bottom): {e:#}");
    }
    Err(e) => eprintln!("import failed: {e:#}"),
    Ok(doc) => { /* proceed */ }
}

Prevention

When it happens

Trigger: Importing a .xopp file whose <image> element lacks the `left` attribute — files generated by external tools, hand-edited XML, or corrupted files missing position attributes (left/right/top/bottom).

Common situations: Custom xopp producers omitting image coordinates; manual XML edits; partial writes dropping attributes; confusion caused by the misleading 'XoppText' wording in the message while debugging image elements.

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/50d63a0404cc4a7c. Report an issue: GitHub.

Appendix: source

Thrown at crates/rnote-engine/src/fileformats/xoppformat.rs:957

    /// The left x position.
    pub left: f64,
    /// The top y position.
    pub top: f64,
    /// The right x position.
    pub right: f64,
    /// The bottom y position.
    pub bottom: f64,
    /// The image data encoded as Png base64.
    pub data: String,
}

impl XmlLoadable for XoppImage {
    fn load_from_xml(&mut self, node: Node) -> anyhow::Result<()> {
        // Left
        self.left = node
            .attribute("left")
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "failed to parse `left` attribute in XoppText with node id {:?}, could not find attribute",
                    node.id()
                )
            })?
            .parse::<f64>()?;

        // Top
        self.top = node
            .attribute("top")
            .ok_or_else(|| {
                anyhow::anyhow!(
                    "failed to parse `top` attribute in XoppText with node id {:?}, could not find attribute",
                    node.id()
                )
            })?
            .parse::<f64>()?;

        // Right

View on GitHub (pinned to bbc5354502)