{"record":{"id":"9f14633291db807e","repo":"astrid-runtime/astrid","slug":"volume-metadata-transaction-must-contain-1-to-1024","errorCode":null,"errorMessage":"volume metadata transaction must contain 1 to 1024 mutations","messagePattern":"volume metadata transaction must contain 1 to 1024 mutations","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage/src/volume/hosted/mod.rs","lineNumber":386,"sourceCode":"        }\n        Self::append(\n            &mut state,\n            Operation::Replace,\n            source,\n            0,\n            destination.as_str().as_bytes(),\n        )?;\n        let source_state = state\n            .regions\n            .remove(source)\n            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, source.as_str()))?;\n        state.regions.insert(destination.clone(), source_state);\n        Ok(())\n    }\n\n    fn commit_metadata(&self, mutations: &[VolumeMetadataMutation]) -> io::Result<()> {\n        if mutations.is_empty() || mutations.len() > MAX_METADATA_MUTATIONS {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidInput,\n                \"volume metadata transaction must contain 1 to 1024 mutations\",\n            ));\n        }\n        let mut state = self.state.lock();\n        let mut next_regions = state.regions.clone();\n        apply_metadata_mutations(&mut next_regions, mutations)?;\n        let payload = encode_metadata_mutations(mutations)?;\n        let transaction = VolumeRegion::new(METADATA_TRANSACTION_REGION)?;\n        Self::append(\n            &mut state,\n            Operation::MetadataTransaction,\n            &transaction,\n            0,\n            &payload,\n        )?;\n        state.regions = next_regions;\n        Ok(())","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage/src/volume/hosted/mod.rs#L368-L404","documentation":"commit_metadata validates that a metadata transaction batch contains between 1 and MAX_METADATA_MUTATIONS (1024) mutations before acquiring the volume state lock. An empty batch carries no work, and batches over 1024 exceed the fixed encoding limit, so the library rejects both with InvalidInput up front. The mutation is not applied and volume state is untouched.","triggerScenarios":"Calling commit_metadata(&[]) with an empty slice, or calling it with more than 1024 VolumeMetadataMutation entries in one transaction.","commonSituations":"Code that collects mutations into a Vec and calls commit_metadata unconditionally without checking the Vec is non-empty (e.g. a rename sweep that found nothing to do); bulk tools that try to push thousands of renames in a single transaction instead of batching.","solutions":["Check mutations.is_empty() before calling and return early (or skip the call) when there is nothing to commit.","Batch mutations into chunks of at most 1024 and call commit_metadata once per chunk.","If >1024 mutations are routine, redesign the caller to commit incrementally rather than accumulating one giant transaction."],"exampleFix":"// before\nvolume.commit_metadata(&mutations)?;\n// after\nfor chunk in mutations.chunks(1024) {\n    if chunk.is_empty() { continue; }\n    volume.commit_metadata(chunk)?;\n}","handlingStrategy":"validation","validationCode":"fn can_commit(mutations: &[VolumeMetadataMutation]) -> bool {\n    !mutations.is_empty() && mutations.len() <= 1024\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never call commit_metadata with an empty mutation list; skip the call instead.","Always chunk mutation batches with .chunks(1024) before committing.","Wrap commit_metadata in a helper that enforces the 1..=1024 invariant in one place."],"tags":["storage","validation","metadata","batching"],"backgroundTag":"value-out-of-range","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}