flxzt/rnote · error · anyhow::Error
stroke components is not a JSON array.
Error message
stroke components is not a JSON array.
What it means
Thrown when the `stroke_components` entry in the engine snapshot exists but is not a JSON array. The migration iterates the components with `.iter_mut()`, which requires an array, so it validates with `as_array_mut()` first.
Solutions
- Unzip the .rnote file and confirm `stroke_components` is a JSON array
- Fix the JSON type manually or regenerate the file from the original data
- In code, coerce/wrap a non-array value into an array before the migration
Example fix
// before
.as_array_mut()
.ok_or(anyhow!("stroke components is not a JSON array."))?;
// after
match engine_snapshot.get_mut("stroke_components").map(|v| v.as_array_mut()) {
Some(Some(arr)) => arr,
_ => return Err(anyhow!("stroke components is not a JSON array.")),
} Defensive patterns
Strategy: type-guard
Validate before calling
match engine_snapshot.get("stroke_components") {
Some(v) if v.as_array().is_some() => {},
_ => return Err(anyhow!("stroke_components must be a JSON array")),
} Type guard
fn stroke_components_is_array(snapshot: &ijson::IObject) -> bool {
snapshot.get("stroke_components").and_then(|v| v.as_array()).is_some()
} Try / catch
// narrow the failing step with context
RnoteFileMaj0Min15::try_from(file_maj0min13)
.with_context(|| "invalid stroke_components type while migrating .rnote file")?; Prevention
- Assert `stroke_components` is an array before iterating
- Never mutate .rnote JSON with untyped scripts
- Validate file JSON with a schema before loading
When it happens
Trigger: Converting an RnoteFileMaj0Min13 whose engine snapshot has `stroke_components` set to an object, string, number, or null instead of an array — usually from corruption or a schema mismatch.
Common situations: Files edited by hand or by scripts that replaced the array with a different JSON type; incompatible snapshots from other tools; truncated writes.
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 component is not a JSON object.
- 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/2aa5ce56b652c22e.
Report an issue: GitHub.
Appendix: source
Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs:29
pub engine_snapshot: ijson::IValue,
}
impl TryFrom<RnoteFileMaj0Min13> for RnoteFileMaj0Min15 {
type Error = anyhow::Error;
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."))?View on GitHub (pinned to bbc5354502)