flxzt/rnote · error · anyhow::Error
stroke component does not contain 'value'.
Error message
stroke component does not contain 'value'.
What it means
This error is thrown during migration of an Rnote file (maj0min13 -> maj0min15) in TryFrom::try_from while iterating stroke_components of the engine snapshot. Each stroke component must be a JSON object with a 'value' key; when serde_json/ijson deserialization yields a component lacking 'value', the migration aborts. It indicates a malformed or hand-edited .rnote file whose stroke component entries deviate from the expected v0.13 schema.
Solutions
- Open the .rnote file in the Rnote version that wrote it and re-save/export it, then retry migration.
- Inspect the JSON inside the .rnote archive (zip) and check every entry in engine_snapshot.stroke_components for a 'value' key.
- Restore the file from a backup or autosave, since the file is likely corrupted or externally modified.
- If repairing manually, add the missing 'value' object (or null — null components are skipped) to the offending component.
Example fix
// repairing a hand-edited stroke component in the .rnote JSON
// before
{"type": "stroke", "brush": "..."}
// after
{"type": "stroke", "value": {"stroke": "..."}, "brush": "..."} Defensive patterns
Strategy: validation
Validate before calling
fn stroke_components_valid(snapshot: &serde_json::Value) -> bool {
snapshot.get("stroke_components")
.and_then(|v| v.as_array())
.map(|arr| arr.iter().all(|c|
c.get("value").map_or(false, |v| v.is_object() || v.is_null())))
.unwrap_or(false)
} Type guard
fn has_value_field(comp: &serde_json::Value) -> bool {
comp.get("value").is_some()
} Try / catch
match RnoteFileMaj0Min15::try_from(file_maj0min13) {
Ok(f) => open(f),
Err(e) if e.to_string().contains("does not contain 'value'") => {
log::error!("corrupt stroke component: {e}");
offer_backup_restore();
}
Err(e) => return Err(e),
} Prevention
- Never hand-edit the JSON payload inside .rnote archives; use Rnote itself.
- Keep .rnote files backed up before upgrading app versions that migrate formats.
- Validate archive JSON against the expected schema before running migrations programmatically.
When it happens
Trigger: Calling TryFrom::<RnoteFileMaj0Min13>::try_from (or the file-open migration path) on a snapshot where some element of engine_snapshot['stroke_components'] is a JSON object without a 'value' key.
Common situations: Opening an .rnote file produced or modified by an incompatible tool version, a partially written/corrupted file, or a hand-edited file where a stroke component's 'value' field was removed or renamed.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- shapestroke does not contain 'shape'.
- vectorimage does not contain 'rectangle'.
- document has no value `layout`.
- engine snapshot does not contain 'stroke_components'.
- value is not a JSON object.
AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08).
Data as JSON: /api/errors/d5077dbe2494d254.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs:36
let engine_snapshot = value
.engine_snapshot
.as_object_mut()
.ok_or(anyhow!("engine snapshot is not a JSON object."))?;
for comp in engine_snapshot
.get_mut("stroke_components")
.ok_or(anyhow!(
"engine snapshot does not contain 'stroke_components'."
))?
.as_array_mut()
.ok_or(anyhow!("stroke components is not a JSON array."))?
.iter_mut()
{
let value = comp
.as_object_mut()
.ok_or(anyhow!("stroke component is not a JSON object."))?
.get_mut("value")
.ok_or(anyhow!("stroke component does not contain 'value'."))?;
if value.is_null() {
continue;
}
if let Some(shapestroke) = value
.as_object_mut()
.ok_or(anyhow!("value is not a JSON object."))?
.get_mut("shapestroke")
{
let shape = shapestroke
.as_object_mut()
.ok_or(anyhow!("shapestroke is not a JSON object."))?
.get_mut("shape")
.ok_or(anyhow!("shapestroke does not contain 'shape'."))?;
if let Some(rect) = shape
.as_object_mut()
.ok_or(anyhow!("shape is not a JSON object."))?
.get_mut("rect")View on GitHub (pinned to bbc5354502)