flxzt/rnote · error · anyhow::Error

affine does not have value at index 0

Error message

affine does not have value at index 0

What it means

Thrown when the "affine" array has no element at index 0. convert_transform_to_affine_in_obj reads indexes 0,1,3,4,6,7 of the affine matrix (row-major 3x3, last row implicit), and a too-short array cannot supply the required values.

Solutions

  1. Ensure "affine" contains at least 8 elements ([a,b,c,d,e,f,g,h]); a full affine is 8 numbers for a 3x3 with the last row fixed.
  2. Restore the file from backup or re-export it.
  3. Fix the producing code to serialize the complete matrix (e.g. [f64; 8]).

Example fix

// before
"affine": []
// after
"affine": [1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
Defensive patterns

Strategy: validation

Validate before calling

let affine = transform.get("affine").and_then(|a| a.as_array())?;
if affine.len() < 8 { return Err(format!("affine too short: {} of 8 elements", affine.len())); }

Type guard

fn is_full_affine(a: &serde_json::Value) -> bool {
    a.as_array().map(|a| a.len() >= 8).unwrap_or(false)
}

Prevention

When it happens

Trigger: Migrating an .rnote file where the transform's "affine" is an array but shorter than 8 elements (empty array fails immediately at index 0).

Common situations: Corrupted or hand-truncated JSON, a writer emitting a partial affine matrix, or a copy/paste edit dropping elements.

Related errors


AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08). Data as JSON: /api/errors/476dc4dc82d5f0c9. Report an issue: GitHub.

Appendix: source

Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min15.rs:140

        .remove("transform")
        .ok_or(anyhow!("rect does not contain 'transform'."))?;
    let transform = transform
        .as_object()
        .ok_or(anyhow!("transform is not a JSON object."))?;
    let affine = transform
        .get("affine")
        .ok_or(anyhow!("transform does not contain 'affine'."))?
        .as_array()
        .ok_or(anyhow!("affine not an array."))?;

    obj.insert(
        "affine",
        vec![
            #[allow(clippy::get_first)]
            affine
                .get(0)
                .cloned()
                .ok_or(anyhow!("affine does not have value at index 0"))?,
            affine
                .get(1)
                .cloned()
                .ok_or(anyhow!("affine does not have value at index 1"))?,
            affine
                .get(3)
                .cloned()
                .ok_or(anyhow!("affine does not have value at index 3"))?,
            affine
                .get(4)
                .cloned()
                .ok_or(anyhow!("affine does not have value at index 4"))?,
            affine
                .get(6)
                .cloned()
                .ok_or(anyhow!("affine does not have value at index 6"))?,
            affine
                .get(7)

View on GitHub (pinned to bbc5354502)