flxzt/rnote · error

store snapshot has no value `chrono_counter`.

Error message

store snapshot has no value `chrono_counter`.

What it means

The maj0min5patch9 -> maj0min6 migration requires `store_snapshot.chrono_counter` to exist, as it becomes `engine_snapshot.chrono_counter` in the new format. This error is thrown when that key is missing from the store snapshot object after the previous keys were removed successfully.

Solutions

  1. Inspect the extracted JSON and add `"chrono_counter": 0` (or the appropriate integer) to the store snapshot.
  2. Restore the document from a backup or autosave copy.
  3. Re-save the file with the rnote version matching its stored format version.
  4. If migrating many files, pre-process them with a script that inserts a default `chrono_counter` before conversion.

Example fix

// before
"store_snapshot": { "stroke_components": [], "chrono_components": [] }
// after
"store_snapshot": { "stroke_components": [], "chrono_components": [], "chrono_counter": 0 }
Defensive patterns

Strategy: validation

Validate before calling

// validate before migration
fn has_chrono_counter(doc: &serde_json::Value) -> bool {
    doc["store_snapshot"].get("chrono_counter").map_or(false, |v| v.is_u64() || v.is_i64())
}

Type guard

fn store_snapshot_has(doc: &serde_json::Value, key: &str) -> bool {
    doc["store_snapshot"].get(key).is_some()
}

Try / catch

match RnoteFileMaj0Min6::try_from(prev) {
    Ok(migrated) => /* use migrated */,
    Err(e) if e.to_string().contains("no value `chrono_counter`") => {
        // insert a default chrono_counter (e.g. 0) and retry
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Running `RnoteFileMaj0Min6::try_from` on a file whose store snapshot contains `stroke_components` and `chrono_components` but no `chrono_counter` key.

Common situations: Files hand-edited with the counter removed, corruption during save, or files from a fork that did not track the chrono counter.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at crates/rnote-engine/src/fileformats/rnoteformat/maj0min6.rs:41

        engine_snapshot.insert(String::from("document"), value.document);
        engine_snapshot.insert(
            String::from("stroke_components"),
            store_snapshot
                .remove("stroke_components")
                .ok_or_else(|| anyhow!("store snapshot has no value `stroke_components`."))?,
        );
        engine_snapshot.insert(
            String::from("chrono_components"),
            store_snapshot
                .remove("chrono_components")
                .ok_or_else(|| anyhow!("store snapshot has no value `chrono_components`."))?,
        );
        engine_snapshot.insert(
            String::from("chrono_counter"),
            store_snapshot
                .remove("chrono_counter")
                .ok_or_else(|| anyhow!("store snapshot has no value `chrono_counter`."))?,
        );

        Ok(Self {
            engine_snapshot: engine_snapshot.into(),
        })
    }
}

View on GitHub (pinned to bbc5354502)