{"record":{"id":"e62e469a790d1080","repo":"flxzt/rnote","slug":"shapestroke-does-not-contain-shape","errorCode":null,"errorMessage":"shapestroke does not contain 'shape'.","messagePattern":"shapestroke does not contain 'shape'\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs","lineNumber":49,"sourceCode":"        {\n            let value = comp\n                .as_object_mut()\n                .ok_or(anyhow!(\"stroke component is not a JSON object.\"))?\n                .get_mut(\"value\")\n                .ok_or(anyhow!(\"stroke component does not contain 'value'.\"))?;\n            if value.is_null() {\n                continue;\n            }\n            if let Some(shapestroke) = value\n                .as_object_mut()\n                .ok_or(anyhow!(\"value is not a JSON object.\"))?\n                .get_mut(\"shapestroke\")\n            {\n                let shape = shapestroke\n                    .as_object_mut()\n                    .ok_or(anyhow!(\"shapestroke is not a JSON object.\"))?\n                    .get_mut(\"shape\")\n                    .ok_or(anyhow!(\"shapestroke does not contain 'shape'.\"))?;\n\n                if let Some(rect) = shape\n                    .as_object_mut()\n                    .ok_or(anyhow!(\"shape is not a JSON object.\"))?\n                    .get_mut(\"rect\")\n                {\n                    convert_transform_to_affine_in_obj(rect)?;\n                } else if let Some(ellipse) = shape\n                    .as_object_mut()\n                    .ok_or(anyhow!(\"shape is not a JSON object.\"))?\n                    .get_mut(\"ellipse\")\n                {\n                    convert_transform_to_affine_in_obj(ellipse)?;\n                }\n            } else if let Some(textstroke) = value\n                .as_object_mut()\n                .ok_or(anyhow!(\"value is not a JSON object.\"))?\n                .get_mut(\"textstroke\")","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs#L31-L67","documentation":"Thrown in TryFrom::<RnoteFileMaj0Min13>::try_from during the maj0min13->maj0min15 migration. A component's 'value.shapestroke' object must contain a 'shape' key describing the geometry (rect or ellipse) whose transform is converted; when 'shape' is absent, the migration fails. This indicates shape-stroke data that does not conform to the v0.13 schema.","triggerScenarios":"try_from hits a component where value['shapestroke'] is an object but has no 'shape' key (e.g. it was renamed to 'geometry' or dropped).","commonSituations":"Files edited by hand or by third-party tools that renamed/dropped the 'shape' field, or corruption in the stroke component payload.","solutions":["Add the missing 'shape' object (with a 'rect' or 'ellipse' entry) to the shapestroke payload.","Re-save the file with the originating Rnote version so the schema is correct, then retry.","Restore the file from a backup or Rnote's autosave.","If the component is unsalvageable, set its 'value' to null so migration skips it."],"exampleFix":"// before\n{\"shapestroke\": {\"style\": {}}}\n// after\n{\"shapestroke\": {\"style\": {}, \"shape\": {\"rect\": {\"transform\": {\"affine\": [1,0,0,1,0,0,0,0,1]}}}}}","handlingStrategy":"validation","validationCode":"fn shapestroke_has_shape(comp: &serde_json::Value) -> bool {\n    comp.get(\"value\")\n        .and_then(|v| v.get(\"shapestroke\"))\n        .and_then(|s| s.get(\"shape\"))\n        .is_some()\n}","typeGuard":"fn get_shape<'a>(shapestroke: &'a serde_json::Value) -> Option<&'a serde_json::Value> {\n    shapestroke.get(\"shape\")\n}","tryCatchPattern":"match RnoteFileMaj0Min15::try_from(file) {\n    Ok(f) => open(f),\n    Err(e) if e.to_string().contains(\"does not contain 'shape'\") => {\n        log::error!(\"shapestroke missing geometry: {e}\");\n        offer_file_repair_or_restore();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify shapestroke objects always carry a 'shape' key before migrating.","Never rename schema keys ('shape', 'value') in .rnote JSON.","Keep pre-migration backups of documents."],"tags":["json","migration","schema-validation","file-format"],"backgroundTag":"missing-required-config-field","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}