{"record":{"id":"bb301915db1afd34","repo":"astrid-runtime/astrid","slug":"region-name-too-long-bb3019","errorCode":null,"errorMessage":"region name too long","messagePattern":"region name too long","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage/src/volume/hosted/stream.rs","lineNumber":101,"sourceCode":"        },\n    }\n}\n\nfn append_from_inner(\n    state: &mut ContainerState,\n    operation: Operation,\n    region: &VolumeRegion,\n    offset: u64,\n    payload_len: u64,\n    payload: &mut dyn Read,\n) -> io::Result<(u64, u64)> {\n    let next_sequence = state\n        .sequence\n        .checked_add(1)\n        .ok_or_else(|| io::Error::other(\"Astrid volume sequence exhausted\"))?;\n    let name = region.as_str().as_bytes();\n    let name_len = u16::try_from(name.len())\n        .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, \"region name too long\"))?;\n    let total_len = u64::try_from(RECORD_FIXED_BYTES)\n        .ok()\n        .and_then(|fixed| fixed.checked_add(u64::from(name_len)))\n        .and_then(|total| total.checked_add(payload_len))\n        .ok_or_else(|| io::Error::other(\"volume record length overflow\"))?;\n    let mut hasher = blake3::Hasher::new_derive_key(\"astrid volume record v1\");\n    hasher.update(&next_sequence.to_le_bytes());\n    hasher.update(&[operation as u8]);\n    hasher.update(&name_len.to_le_bytes());\n    hasher.update(&offset.to_le_bytes());\n    hasher.update(&payload_len.to_le_bytes());\n    hasher.update(name);\n\n    // The previous footer ends at `valid_len`; remove it before publishing a\n    // new record. A failed stream leaves footer_pending set so the next sync\n    // restores the prior durable footer.\n    state.flush_state = super::FlushState::Required;\n    state.footer_pending = true;","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage/src/volume/hosted/stream.rs#L83-L119","documentation":"When serializing a record, the region name is length-prefixed with a u16 on disk. append_from_inner converts the region name's byte length to u16 and fails with InvalidInput if the name exceeds 65535 bytes. This guards the on-disk record format, which cannot represent longer names.","triggerScenarios":"append_from (via append_from_inner) is given a region whose as_str().as_bytes() length is > 65535 — callers constructing region names from unbounded user input, concatenations, or long identifiers.","commonSituations":"User-supplied or templated region names pasted into the volume API without validation; generated names built by concatenating prefixes/IDs that grow unbounded; names containing multi-byte UTF-8 whose byte length (not char count) exceeds the limit.","solutions":["Validate region names at your API boundary: reject names whose byte length exceeds 65535 (ideally far lower) before creating/writing the region.","Truncate or hash long identifiers into a bounded name (e.g. blake3/sha256 hex, ≤64 chars) instead of using raw long strings.","Count bytes, not characters, when validating names with non-ASCII content.","Check where the name is assembled; cap the size of each concatenated component."],"exampleFix":"// before\nlet name = format!(\"regions/{}:{}:{}\", tenant, path, full_blob_id);\nvolume.write_region_from(&name, offset, payload)?;\n// after\nlet digest = blake3::hash(full_blob_id.as_bytes()).to_hex()[..32].to_string();\nlet name = format!(\"r/{}:{}\", tenant_short, digest);\nassert!(name.len() <= 255);\nvolume.write_region_from(&name, offset, payload)?;","handlingStrategy":"validation","validationCode":"// Rust: validate name before calling the volume API\nfn valid_region_name(name: &str) -> bool {\n    !name.is_empty() && name.len() <= 255 // byte length, well under u16::MAX\n}\nif !valid_region_name(&region) { return Err(\"region name too long\"); }","typeGuard":null,"tryCatchPattern":"match volume.write_region_from(&region, offset, payload).await {\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains(\"region name too long\") => {\n        // hash/shorten the identifier and retry with a bounded name\n    }\n    other => other?,\n}","preventionTips":["Validate region-name byte length at your API boundary (cap far below 65535).","Hash long identifiers instead of embedding raw paths/user input in names.","Remember byte length != character count for non-ASCII names.","Add a unit test covering the maximum accepted name length."],"tags":["storage","validation","limits","region-name"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}