{"record":{"id":"b220de10abba784c","repo":"flxzt/rnote","slug":"value-in-stroke-components-array-is-not-a-json-o","errorCode":null,"errorMessage":"value in `stroke_components` array is not a JSON Object.","messagePattern":"value in `stroke_components` array is not a JSON Object\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/fileformats/rnoteformat/maj0min5patch9.rs","lineNumber":33,"sourceCode":"    #[serde(rename = \"store_snapshot\")]\n    pub(crate) store_snapshot: ijson::IValue,\n}\n\nimpl TryFrom<RnoteFileMaj0Min5Patch8> for RnoteFileMaj0Min5Patch9 {\n    type Error = anyhow::Error;\n\n    fn try_from(mut file: RnoteFileMaj0Min5Patch8) -> Result<RnoteFileMaj0Min5Patch9, Self::Error> {\n        let stroke_components = file\n            .store_snapshot\n            .get_mut(\"stroke_components\")\n            .ok_or_else(|| anyhow!(\"no value `stroke_components` in `store_snapshot`\"))?\n            .as_array_mut()\n            .ok_or_else(|| anyhow!(\"value `stroke_components` is not a JSON array.\"))?;\n\n        for value in stroke_components {\n            let stroke = value\n                .as_object_mut()\n                .ok_or_else(|| anyhow!(\"value in `stroke_components` array is not a JSON Object.\"))?\n                .get_mut(\"value\")\n                .ok_or_else(|| {\n                    anyhow!(\"no value `value` in JSON object of `stroke_components` array.\")\n                })?;\n\n            if stroke.is_null() {\n                continue;\n            }\n\n            if let Some(brushstroke) = stroke\n                .as_object_mut()\n                .ok_or_else(|| anyhow!(\"stroke value is not a JSON Object.\"))?\n                .get_mut(\"brushstroke\")\n            {\n                let brushstroke = brushstroke\n                    .as_object_mut()\n                    .ok_or_else(|| anyhow!(\"brushstroke is not a JSON object.\"))?;\n                let path = ijson::from_value::<PenPathMaj0Min5Patch8>(","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/fileformats/rnoteformat/maj0min5patch9.rs#L15-L51","documentation":"Thrown while iterating the \"stroke_components\" array when an element is not a JSON object. The migration expects each entry to be an object containing a \"value\" key it can rewrite, so a non-object element aborts the conversion.","triggerScenarios":"An .rnote file where store_snapshot[\"stroke_components\"] is an array but at least one element is a string, number, null, or array rather than an object.","commonSituations":"Corrupted files from partial writes, hand edits inserting raw values, or a custom generator emitting the wrong element shape.","solutions":["Fix each stroke_components element to be a JSON object with a \"value\" key (or remove invalid entries).","Re-save the file from the app version that produced a valid snapshot.","Restore from backup and avoid manual edits to snapshot internals."],"exampleFix":"// before\n\"stroke_components\": [null]\n// after\n\"stroke_components\": [ { \"value\": null } ]","handlingStrategy":"validation","validationCode":"for (i, el) in comps.iter().enumerate() {\n    if !el.is_object() {\n        return Err(format!(\"stroke_components[{i}] is not a JSON object\"));\n    }\n}","typeGuard":"fn all_strokes_are_objects(arr: &[serde_json::Value]) -> bool {\n    arr.iter().all(|v| v.is_object() && v.get(\"value\").is_some())\n}","tryCatchPattern":"// sanitize before migrating\nlet comps: Vec<serde_json::Value> = comps.into_iter().filter(|v| v.is_object()).collect();","preventionTips":["Sanitize arrays by filtering non-object entries before migration when corruption is suspected.","Never insert raw values into stroke_components by hand.","Validate each element's shape (object with a \"value\" key) at import."],"tags":["json","file-migration","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}