astrid-runtime/astrid · error
message
Error message
message
What it means
invalid_transition is the shared constructor for InvalidData errors raised while decoding or applying volume metadata/footer structures. The displayed message "message" is the function's parameter name; the real message comes from each call site (e.g. "metadata region name is not UTF-8"). It signals that the on-disk structure is inconsistent with the expected format at that point.
Solutions
- Read the real message inside the error to identify which structural check failed.
- Run recovery (recover_container) so the volume resynchronizes to the last valid commit.
- Confirm the writer and reader use compatible astrid-storage versions/formats.
- Restore the volume from backup if the footer/metadata region is physically corrupt.
Defensive patterns
Strategy: try-catch
Try / catch
match decode_metadata(file, offset) {
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
eprintln!("metadata structure invalid: {e}; running recovery");
recover_container(file)?;
}
other => other,
} Prevention
- Run recovery on open rather than hand-decoding metadata regions.
- Never manually edit or truncate volume files.
- Sync cleanly on shutdown so the footer is not torn mid-write.
- Keep format versions compatible between writer and reader.
When it happens
Trigger: Any of its callers hit malformed data: decode_metadata_mutations reading bad kind/length fields, read_u16 or read_metadata_region hitting EOF mid-field, a region name failing UTF-8 validation, encode_region_snapshot/write_footer invariant failures, or apply_metadata_mutations encountering an impossible region transition.
Common situations: Disk corruption or torn writes in the volume footer/metadata area; a volume written by a different (incompatible) format version; manually editing or truncating the volume file; decoding at a stale offset after an interrupted commit.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- durable capsule metadata names a component absent from its…
- durable capsule metadata names a hash for a non-WASM…
- invalid Astrid volume header
- invalid Astrid volume record magic at
- metadata region name too long
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/a8b984b585ef277f.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage/src/volume/hosted/mod.rs:592
})?))
}
fn read_metadata_region(bytes: &[u8], cursor: &mut usize) -> io::Result<VolumeRegion> {
let length = usize::from(read_u16(bytes, cursor)?);
let end = cursor
.checked_add(length)
.ok_or_else(|| invalid_transition("metadata region name length overflow"))?;
let name = bytes
.get(*cursor..end)
.ok_or_else(|| invalid_transition("truncated metadata region name"))?;
*cursor = end;
let name = std::str::from_utf8(name)
.map_err(|_| invalid_transition("metadata region name is not UTF-8"))?;
VolumeRegion::new(name.to_owned())
}
fn invalid_transition(message: &'static str) -> io::Error {
io::Error::new(io::ErrorKind::InvalidData, message)
}
fn overlapping_extents(
region_state: &RegionState,
offset: u64,
read_end: u64,
) -> Vec<(u64, Extent)> {
let start_key = region_state
.extents
.range(..=offset)
.next_back()
.and_then(|(start, extent)| (extent.logical_end > offset).then_some(*start))
.unwrap_or(offset);
let mut overlaps = Vec::new();
for (start, extent) in region_state.extents.range(start_key..read_end) {
#[cfg(test)]
EXTENT_VISITS.with(|count| count.set(count.get().saturating_add(1)));
if extent.logical_end > offset {View on GitHub (pinned to affd8760f4)