{"record":{"id":"f839b808efce588c","repo":"zed-industries/zed","slug":"invalid-git-oid-byte-length-expected-sha1-byte-l","errorCode":null,"errorMessage":"invalid git oid byte length: expected {SHA1_BYTE_LENGTH} for SHA-1 or {SHA256_BYTE_LENGTH} for SHA-256, got {len}","messagePattern":"invalid git oid byte length: expected (.+?) for SHA-1 or (.+?) for SHA-256, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git/src/git.rs","lineNumber":209,"sourceCode":"            Self::Sha256 => SHA256_BYTE_LENGTH,\n        }\n    }\n\n    fn hex_len(self) -> usize {\n        match self {\n            Self::Sha1 => SHA1_HEX_LENGTH,\n            Self::Sha256 => SHA256_HEX_LENGTH,\n        }\n    }\n}\n\nimpl Oid {\n    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {\n        let format = match bytes.len() {\n            SHA1_BYTE_LENGTH => OidFormat::Sha1,\n            SHA256_BYTE_LENGTH => OidFormat::Sha256,\n            len => {\n                anyhow::bail!(\n                    \"invalid git oid byte length: expected {SHA1_BYTE_LENGTH} for SHA-1 or {SHA256_BYTE_LENGTH} for SHA-256, got {len}\"\n                );\n            }\n        };\n\n        let mut oid_bytes = [0u8; SHA256_BYTE_LENGTH];\n        oid_bytes[..bytes.len()].copy_from_slice(bytes);\n        Ok(Self {\n            bytes: oid_bytes,\n            format,\n        })\n    }\n\n    #[cfg(any(test, feature = \"test-support\"))]\n    pub fn random(rng: &mut impl rand::Rng) -> Self {\n        let mut bytes = [0u8; SHA256_BYTE_LENGTH];\n        rng.fill(&mut bytes[..SHA1_BYTE_LENGTH]);\n        Self {","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/git/src/git.rs#L191-L227","documentation":"Oid::from_bytes accepts only the two raw object-id byte lengths git uses: 20 bytes (SHA-1) or 32 bytes (SHA-256); anything else bails with the observed length. The bytes are then zero-padded into a fixed 32-byte array tagged with the detected format, so a wrong length cannot be guessed. This is the binary counterpart of the hex-length check in FromStr.","triggerScenarios":"Calling Oid::from_bytes with hex-string bytes (40 or 64 ASCII characters), a truncated hash, a 20-byte buffer off by slicing, or object ids from a non-git source with arbitrary length.","commonSituations":"Accidentally passing a hex oid's UTF-8 bytes instead of decoded bytes, slicing an oid buffer with the wrong range, or handling shortened/abbreviated ids through the byte API.","solutions":["If the input is hex text, use Oid::from_str / str::parse instead of from_bytes","If it is raw, ensure exactly 20 (SHA-1) or 32 (SHA-256) bytes — check slicing ranges and the source of the buffer","Validate length at the boundary where external ids enter your code"],"exampleFix":"// before\nlet oid = Oid::from_bytes(hex_oid.as_bytes())?; // 40 bytes of ASCII -> invalid git oid byte length ... got 40\n\n// after\nlet oid = Oid::from_str(hex_oid)?;","handlingStrategy":"type-guard","validationCode":"if bytes.len() != 20 && bytes.len() != 32 {\n    return Err(format!(\"refusing to build Oid from {} bytes\", bytes.len()));\n}","typeGuard":"fn is_valid_oid_byte_length(len: usize) -> bool {\n    matches!(len, 20 | 32)\n}","tryCatchPattern":"let oid = match Oid::from_bytes(bytes) {\n    Ok(oid) => oid,\n    Err(e) if e.to_string().contains(\"oid byte length\") => Oid::from_str(&String::from_utf8_lossy(bytes))?,\n    Err(e) => return Err(e),\n};","preventionTips":["Use from_str for hex input and from_bytes only for decoded raw ids","Assert buffer lengths at the boundary where external ids enter"],"tags":["git","oid","sha1","sha256","validation"],"backgroundTag":"invalid-git-oid","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}