flxzt/rnote · error · anyhow::Error
no value `value` in JSON object of `stroke_components`…
Error message
no value `value` in JSON object of `stroke_components` array.
What it means
During the maj0min5patch8 -> maj0min5patch9 rnote file format migration, each element of the `stroke_components` JSON array must be an object containing a `value` key. This error is thrown when such an object exists but has no `value` field, so the migration cannot unwrap the inner stroke data.
Solutions
- Verify the .rnote file is intact (unzip it and inspect the JSON's stroke_components entries; each must contain `value`).
- Recover the file from a backup or autosave copy instead of repairing the corrupt one manually.
- If repairing manually, add the `value` key wrapping the stroke payload in each affected stroke_components element.
- Check whether the file was written by a different/older rnote version and re-export it with a matching version.
Example fix
// before (corrupt entry)
{ "stroke_components": [ { "brushstroke": {...} } ] }
// after (fixed)
{ "stroke_components": [ { "value": { "brushstroke": {...} } } ] } Defensive patterns
Strategy: validation
Validate before calling
// validate before migration
fn stroke_components_valid(doc: &serde_json::Value) -> bool {
doc["store_snapshot"]["stroke_components"]
.as_array()
.map(|arr| arr.iter().all(|v| v.get("value").is_some()))
.unwrap_or(false)
} Type guard
fn has_value_field(entry: &serde_json::Value) -> bool {
entry.is_object() && entry.get("value").is_some()
} Try / catch
match RnoteFileMaj0Min5Patch9::try_from(file) {
Ok(migrated) => /* use migrated */,
Err(e) if e.to_string().contains("stroke_components") => {
// recover from backup or repair JSON structure
}
Err(e) => return Err(e),
} Prevention
- Never hand-edit .rnote JSON without checking rnoteformat's expected schema for the file version.
- Keep automatic backups/autosave of .rnote documents before any migration.
- Reject or quarantine files whose stroke_components entries lack `value` at ingest time.
- Test migrations on a copy of the file first.
When it happens
Trigger: Calling `RnoteFileMaj0Min5Patch9::try_from` on a file whose `store_snapshot.stroke_components` array contains a JSON object lacking the `value` key; typically a corrupted, hand-edited, or partially written .rnote file.
Common situations: Opening an .rnote file that was truncated mid-save, produced by a buggy exporter, or manually edited where the wrapper `{ "value": ... }` around each stroke component was dropped.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- document has no value `layout`.
- engine snapshot does not contain 'stroke_components'.
- stroke component does not contain 'value'.
- value is not a JSON object.
- shapestroke is not a JSON object.
AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08).
Data as JSON: /api/errors/e37f2e7e499958e2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min5patch9.rs:36
impl TryFrom<RnoteFileMaj0Min5Patch8> for RnoteFileMaj0Min5Patch9 {
type Error = anyhow::Error;
fn try_from(mut file: RnoteFileMaj0Min5Patch8) -> Result<RnoteFileMaj0Min5Patch9, Self::Error> {
let stroke_components = file
.store_snapshot
.get_mut("stroke_components")
.ok_or_else(|| anyhow!("no value `stroke_components` in `store_snapshot`"))?
.as_array_mut()
.ok_or_else(|| anyhow!("value `stroke_components` is not a JSON array."))?;
for value in stroke_components {
let stroke = value
.as_object_mut()
.ok_or_else(|| anyhow!("value in `stroke_components` array is not a JSON Object."))?
.get_mut("value")
.ok_or_else(|| {
anyhow!("no value `value` in JSON object of `stroke_components` array.")
})?;
if stroke.is_null() {
continue;
}
if let Some(brushstroke) = stroke
.as_object_mut()
.ok_or_else(|| anyhow!("stroke value is not a JSON Object."))?
.get_mut("brushstroke")
{
let brushstroke = brushstroke
.as_object_mut()
.ok_or_else(|| anyhow!("brushstroke is not a JSON object."))?;
let path = ijson::from_value::<PenPathMaj0Min5Patch8>(
&brushstroke
.remove("path")
.ok_or_else(|| anyhow!("brushstroke has no value `path`."))?,View on GitHub (pinned to bbc5354502)