astrid-runtime/astrid · error

metadata region name too long

Error message

metadata region name too long

What it means

Each region name in a metadata mutation is length-prefixed with a u16, so a region name may be at most 65535 bytes. Longer names cannot be encoded and are rejected with InvalidInput. Note the encoder emits both source and destination for every mutation, so either may trip this.

Source

Thrown at crates/astrid-storage/src/volume/hosted/mod.rs:518

        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "too many metadata mutations"))?;
    let mut output = Vec::new();
    output.extend_from_slice(&count.to_le_bytes());
    for mutation in mutations {
        let (kind, source, destination) = match mutation {
            VolumeMetadataMutation::Rename {
                source,
                destination,
            } => (1_u8, source, destination),
            VolumeMetadataMutation::Replace {
                source,
                destination,
            } => (2_u8, source, destination),
        };
        output.push(kind);
        for region in [source, destination] {
            let bytes = region.as_str().as_bytes();
            let length = u16::try_from(bytes.len()).map_err(|_| {
                io::Error::new(io::ErrorKind::InvalidInput, "metadata region name too long")
            })?;
            output.extend_from_slice(&length.to_le_bytes());
            output.extend_from_slice(bytes);
        }
    }
    Ok(output)
}

fn decode_metadata_mutations(bytes: &[u8]) -> io::Result<Vec<VolumeMetadataMutation>> {
    let mut cursor = 0_usize;
    let count = usize::from(read_u16(bytes, &mut cursor)?);
    if count == 0 || count > MAX_METADATA_MUTATIONS {
        return Err(invalid_transition("invalid metadata transaction count"));
    }
    let mut mutations = Vec::with_capacity(count);
    for _ in 0..count {
        let kind = *bytes
            .get(cursor)

View on GitHub (pinned to affd8760f4)

Solutions

  1. Validate region name length (e.g. keep it well under 64 KiB, ideally a small fixed cap) when constructing VolumeRegion::new.
  2. Truncate or reject over-long names at the API boundary that builds mutations.
  3. If names legitimately need to be long, store an identifier/alias in the region name instead of the full payload.

Example fix

// before
let region = VolumeRegion::new(generated_name);
// after
assert!(generated_name.len() <= u16::MAX as usize, "region name too long");
let region = VolumeRegion::new(generated_name);
Defensive patterns

Strategy: validation

Validate before calling

fn region_name_encodable(name: &str) -> bool {
    name.as_bytes().len() <= u16::MAX as usize
}

Prevention

When it happens

Trigger: Encoding a Rename (or other two-region) mutation whose source or destination VolumeRegion string exceeds 65535 bytes when UTF-8 encoded.

Common situations: Programmatically generated region names (hashes, templated paths) that grew unbounded; user-supplied names concatenated with long prefixes; fuzzing or property tests feeding huge strings.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/8f4de04f556b5702. Report an issue: GitHub.