flxzt/rnote · error
failed to parse `color` attribute in XoppStroke with node id
Error message
failed to parse `color` attribute in XoppStroke with node id {:?}, could not find attribute What it means
Thrown by XoppStroke::load_from_xml when a `<stroke>` element has no `color` attribute. The parser passes the attribute value to XoppColor::from_strokecolor_attr_value, and it uses ok_or_else to raise this error (with the node id) when the attribute is absent, since a stroke color is mandatory in the XOPP format.
Solutions
- Add a color attribute to the stroke element, e.g. color="black" or color="#ff0000ff".
- Regenerate the file ensuring every <stroke> element includes color.
- Open and re-save the file in Xournal++ to restore required attributes, then re-import.
- Validate the XML against the XOPP schema/known attribute set before importing.
Example fix
// before (file XML) <stroke tool="pen" width="2.26">...</stroke> // after (file XML) <stroke tool="pen" width="2.26" color="black">...</stroke>
Defensive patterns
Strategy: validation
Validate before calling
fn stroke_elements_have_color(xml: &str) -> Result<(), String> {
for (i, chunk) in xml.split("<stroke").skip(1).enumerate() {
let head = chunk.split('>').next().unwrap_or("");
if !head.contains("color=") {
return Err(format!("stroke #{i} missing `color` attribute"));
}
}
Ok(())
} Type guard
fn stroke_attrs_ok(attrs: &[(&str, &str)]) -> bool {
attrs.iter().any(|(k, _)| *k == "color")
} Try / catch
match import_xopp(path) {
Err(e) if e.to_string().contains("`color` attribute in XoppStroke") => {
eprintln!("A stroke element is missing its color; fix the XML or re-save in Xournal++: {e:#}");
}
Err(e) => eprintln!("import failed: {e:#}"),
Ok(doc) => { /* proceed */ }
} Prevention
- When scripting xopp generation, always emit tool, color, and width on every <stroke>
- Use a checklist of mandatory XOPP attributes in your generator code
- Round-trip generated files through Xournal++ to verify validity
When it happens
Trigger: Importing a .xopp file whose `<stroke>` element is missing the `color` attribute — typically hand-edited files, scripts generating xopp XML without color, or files edited by non-Xournal++ tools that dropped the attribute.
Common situations: Custom export/generation scripts producing incomplete stroke XML; manual XML edits removing color; corrupted or partially written 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 `width` attribute in XoppStroke with node id
- failed to parse `font` attribute in XoppText 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/820bed6fbe038680.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/xoppformat.rs:723
"failed to parse `tool` attribute in XoppStroke with node id {:?}, could not find attribute",
node.id()
)
})? {
"pen" => {
self.tool = XoppTool::Pen;
}
"highlighter" => {
self.tool = XoppTool::Highlighter;
}
"eraser" => {
self.tool = XoppTool::Eraser;
}
_ => {}
}
self.color =
XoppColor::from_strokecolor_attr_value(node.attribute("color").ok_or_else(|| {
anyhow::anyhow!(
"failed to parse `color` attribute in XoppStroke with node id {:?}, could not find attribute",
node.id()
)
})?)?;
self.fill = if let Some(fill) = node.attribute("fill") {
Some(fill.parse::<i32>()?)
} else {
None
};
self.width = node
.attribute("width")
.ok_or_else(|| {
anyhow::anyhow!(
"failed to parse `width` attribute in XoppStroke with node id {:?}, could not find attribute",
node.id()
)View on GitHub (pinned to bbc5354502)