{"record":{"id":"80d386f73f6af56f","repo":"BoundaryML/baml","slug":"invalid-sha256-blob-digest-expected-only-hex-characters","errorCode":null,"errorMessage":"invalid sha256 blob digest; expected only hex characters","messagePattern":"invalid sha256 blob digest; expected only hex characters","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_events/src/value/artifact.rs","lineNumber":55,"sourceCode":"    pub fn validate(&self) -> io::Result<()> {\n        if self.algorithm != Self::ALGORITHM_SHA256 {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\"unsupported blob algorithm `{}`\", self.algorithm),\n            ));\n        }\n        if self.digest.len() != Self::SHA256_HEX_LEN {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"invalid sha256 blob digest length {}; expected {} hex characters\",\n                    self.digest.len(),\n                    Self::SHA256_HEX_LEN\n                ),\n            ));\n        }\n        if !self.digest.bytes().all(|byte| byte.is_ascii_hexdigit()) {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                \"invalid sha256 blob digest; expected only hex characters\",\n            ));\n        }\n        Ok(())\n    }\n\n    fn normalized_digest(&self) -> io::Result<String> {\n        self.validate()?;\n        Ok(self.digest.to_ascii_lowercase())\n    }\n\n    fn verify_bytes(&self, bytes: &[u8]) -> io::Result<()> {\n        if bytes.len() != self.size_bytes {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"blob size mismatch for {}; expected {} bytes, got {} bytes\",","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_events/src/value/artifact.rs#L37-L73","documentation":"BlobRef::validate additionally requires every byte of the sha256 digest to be an ASCII hex digit (0-9, a-f, A-F). This error means the digest has the right length (64 chars) but contains non-hex characters, so it cannot be a valid SHA-256 representation. It is raised from normalized_digest via validate on any blob operation.","triggerScenarios":"A 64-character digest containing e.g. 'g'-'z', '0x' prefixes, padding characters, or binary garbage; encountered through normalized_digest(), write_blob(), read_blob(), or path_for().","commonSituations":"Digests produced by a custom hasher that emits base64, digests pasted from hex viewers with prefixes (0x), corrupted event files, or digests constructed via encoding mistakes (e.g. encoding raw bytes as utf8 instead of hex).","solutions":["Regenerate the digest using a hex encoder over the SHA-256 bytes (e.g. hex-encode the 32-byte hash).","Strip any prefixes/decorations (0x, sha256:) from the digest string before storing it.","If the digest is supposed to be binary-encoded, decode it properly instead of storing raw bytes as a string."],"exampleFix":"// before\nlet digest = String::from_utf8(sha256_bytes)?; // non-hex garbage\n// after\nlet digest = hex::encode(sha256_bytes); // 64 ascii hex chars","handlingStrategy":"validation","validationCode":"fn is_hex(s: &str) -> bool { !s.is_empty() && s.bytes().all(|b| b.is_ascii_hexdigit()) }\nif digest.len() != 64 || !is_hex(&digest) { /* recompute from source bytes */ }","typeGuard":"fn is_hex_digest(s: &str) -> bool { s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit()) }","tryCatchPattern":"let digest = blob_ref.normalized_digest().map_err(|e| {\n    eprintln!(\"invalid blob digest: {e}\");\n    e\n})?;","preventionTips":["Hex-encode raw hash bytes with a dedicated hex encoder; never build digest strings from utf8 conversion.","Strip prefixes like 'sha256:' or '0x' before storing digests.","Centralize digest creation in one function so encoding is consistent."],"tags":["rust","validation","blob-storage","checksum"],"backgroundTag":"invalid-argument-format","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}