flxzt/rnote · error · anyhow::Error
stroke component is not a JSON object.
Error message
stroke component is not a JSON object.
What it means
Thrown when an element of the `stroke_components` array is not a JSON object. Each component must be an object containing a `value` key that the migration can transform; scalar/array elements cannot be processed.
Solutions
- Inspect the stroke_components array in the .rnote JSON and remove/repair the malformed element
- Re-export the document from the rnote version that created it
- In code, skip or default elements that are not objects instead of aborting the whole migration
Example fix
// before
let value = comp
.as_object_mut()
.ok_or(anyhow!("stroke component is not a JSON object."))?;
// after
let Some(comp_obj) = comp.as_object_mut() else {
log::warn!("skipping non-object stroke component");
continue;
};
let value = comp_obj
.get_mut("value")
.ok_or(anyhow!("stroke component does not contain 'value'."))?; Defensive patterns
Strategy: validation
Validate before calling
let all_objects = engine_snapshot["stroke_components"]
.as_array()
.map(|a| a.iter().all(|c| c.as_object().is_some()))
.unwrap_or(false);
if !all_objects {
return Err(anyhow!("every stroke component must be a JSON object"));
} Type guard
fn components_are_objects(snapshot: &ijson::IObject) -> bool {
snapshot.get("stroke_components")
.and_then(|v| v.as_array())
.map(|a| a.iter().all(|c| c.as_object().is_some()))
.unwrap_or(false)
} Try / catch
// catch and report the index of the bad component after repair tooling
let file = RnoteFileMaj0Min15::try_from(file_maj0min13)
.map_err(|e| anyhow!("malformed stroke component while migrating: {e:#}"))?; Prevention
- Validate every element of stroke_components is an object before conversion
- Skip or quarantine malformed components instead of writing them into the file
- Test migrations against truncated/corrupted fixtures
When it happens
Trigger: Iterating stroke components during the maj0min13 -> maj0min15 conversion when one array element is a non-object JSON value — e.g. null, a string, or a nested array from a corrupt or malformed file.
Common situations: Damaged .rnote archives with partially written component arrays; hand-edited JSON; fixtures generated by other tooling with the wrong component shape.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- engine snapshot is not a JSON object.
- stroke components is not a JSON array.
- 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/7528a1dba4d8789c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs:34
fn try_from(mut value: RnoteFileMaj0Min13) -> Result<Self, Self::Error> {
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()View on GitHub (pinned to bbc5354502)