{"record":{"id":"9f9c2c8390bee638","repo":"zed-industries/zed","slug":"invalid-git-oid-hex-length-expected-1-sha1-hex","errorCode":null,"errorMessage":"invalid git oid hex length: expected 1..={SHA1_HEX_LENGTH} for SHA-1 or {SHA256_HEX_LENGTH} for SHA-256, got {len}","messagePattern":"invalid git oid hex length: expected 1\\.\\.=(.+?) for SHA-1 or (.+?) for SHA-256, got (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/git/src/git.rs","lineNumber":290,"sourceCode":"}\n\nimpl TryFrom<&str> for Oid {\n    type Error = anyhow::Error;\n\n    fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {\n        Oid::from_str(value)\n    }\n}\n\nimpl FromStr for Oid {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {\n        let format = match s.len() {\n            1..=SHA1_HEX_LENGTH => OidFormat::Sha1,\n            SHA256_HEX_LENGTH => OidFormat::Sha256,\n            len => {\n                anyhow::bail!(\n                    \"invalid git oid hex length: expected 1..={SHA1_HEX_LENGTH} for SHA-1 or {SHA256_HEX_LENGTH} for SHA-256, got {len}\"\n                );\n            }\n        };\n\n        let mut bytes = [0u8; SHA256_BYTE_LENGTH];\n        for (index, byte) in s.bytes().enumerate() {\n            let digit = decode_hex_digit(byte)\n                .ok_or_else(|| anyhow::anyhow!(\"invalid hex digit at byte {index} for git oid\"))?;\n            if index % 2 == 0 {\n                bytes[index / 2] = digit << 4;\n            } else {\n                bytes[index / 2] |= digit;\n            }\n        }\n\n        Ok(Self { bytes, format })\n    }","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/git/src/git.rs#L272-L308","documentation":"Oid::from_str classifies the hex string purely by length: 1..=40 hex chars are treated as an abbreviated-or-full SHA-1 oid, exactly 64 as SHA-256, and anything else bails with the observed length. There is deliberately no middle ground — 41-63 chars, 0 chars (empty string), or >64 are all rejected before any hex-digit decoding happens.","triggerScenarios":"Parsing an oid string with 41–63 hex characters (e.g. a SHA-1 with appended characters or a truncated SHA-256), an empty string, a 65+ char string, or text with whitespace/newlines inflating the length.","commonSituations":"Splitting git output on the wrong delimiter leaving trailing characters, concatenated oids not re-split, user-pasted revs with spaces or newlines, or copying 64+ char strings from non-git tools.","solutions":["Trim whitespace/newlines from the string before parsing","Check the length: use a full 40-char SHA-1, an abbreviation of 1–40 chars, or a full 64-char SHA-256","Fix the upstream splitting/format string (e.g. %x00 delimiters) so oids arrive clean"],"exampleFix":"// before\nlet oid: Oid = line_with_trailing_newline.parse()?; // len 41 -> invalid git oid hex length\n\n// after\nlet oid = Oid::from_str(line.trim())?;","handlingStrategy":"type-guard","validationCode":"let s = s.trim();\nif !(1..=40).contains(&s.len()) && s.len() != 64 {\n    return Err(format!(\"oid string has invalid length {}\", s.len()));\n}","typeGuard":"fn is_valid_oid_hex(s: &str) -> bool {\n    let len = s.len();\n    ((1..=40).contains(&len) || len == 64) && s.bytes().all(|b| b.is_ascii_hexdigit())\n}","tryCatchPattern":"let oid = match Oid::from_str(raw) {\n    Ok(oid) => oid,\n    Err(e) if e.to_string().contains(\"hex length\") => Oid::from_str(raw.trim())?,\n    Err(e) => return Err(e),\n};","preventionTips":["Trim every oid parsed from split output; delimiters and newlines inflate the length","Remember 41–63 chars are always invalid — no abbreviation exists in that range"],"tags":["git","oid","hex","validation","parse"],"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-14T00:17:10.932Z"}