{"record":{"id":"ecd3eba56541065a","repo":"jdx/mise","slug":"remote-cache-blob-pack-has-an-invalid-digest-algor","errorCode":null,"errorMessage":"remote cache blob pack has an invalid digest algorithm","messagePattern":"remote cache blob pack has an invalid digest algorithm","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mise-cache-core/src/lib.rs","lineNumber":918,"sourceCode":"    }\n\n    let directory = tempfile::tempdir_in(staging_dir)?;\n    let mut seen = BTreeSet::new();\n    let mut blobs = Vec::new();\n    let mut payload_bytes = 0_u64;\n    let mut framed_bytes = BLOB_PACK_MAGIC.len() as u64;\n    loop {\n        let mut algorithm = [0_u8; 1];\n        if reader.read(&mut algorithm).await? == 0 {\n            break;\n        }\n        let (algorithm, mut hasher) = match algorithm[0] {\n            1 => (\n                \"blake3\",\n                BlobPackHasher::Blake3(Box::new(blake3::Hasher::new())),\n            ),\n            2 => (\"sha256\", BlobPackHasher::Sha256(sha2::Sha256::new())),\n            _ => bail!(\"remote cache blob pack has an invalid digest algorithm\"),\n        };\n        let mut hash = [0_u8; 32];\n        reader.read_exact(&mut hash).await?;\n        let mut size = [0_u8; 8];\n        reader.read_exact(&mut size).await?;\n        let digest = CacheDigest {\n            algorithm: algorithm.into(),\n            hash: hex::encode(hash),\n            size: u64::from_be_bytes(size),\n        };\n        if !requested.contains(&digest) {\n            bail!(\"remote cache blob pack returned an unrequested digest\");\n        }\n        if !seen.insert(digest.clone()) {\n            bail!(\"remote cache blob pack returned a duplicate digest\");\n        }\n        framed_bytes = framed_bytes\n            .checked_add(BLOB_PACK_HEADER_BYTES)","sourceCodeStart":900,"sourceCodeEnd":936,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/crates/mise-cache-core/src/lib.rs#L900-L936","documentation":"Thrown inside decode_blob_pack's record loop (crates/mise-cache-core/src/lib.rs:918): each blob record starts with a 1-byte algorithm tag — 1 maps to blake3, 2 maps to sha256 — and any other byte bails with this error. The tag selects the hasher used to verify the record's subsequent 32-byte hash and 8-byte big-endian size, so an unknown tag means the record cannot be verified or interpreted.","triggerScenarios":"A blob pack body whose per-record algorithm byte is not 0x01 or 0x02 — e.g. a newer pack format that added algorithm tags (sha512 = 3?), a hand-crafted pack with the wrong tag, or byte-stream corruption/desynchronization where the reader is misaligned and reads a hash byte as the tag (usually preceded by other symptoms).","commonSituations":"Version skew after a pack format extension; a custom server writing tags this decoder predates; stream desync caused by an earlier record with a wrong size field — the loop then reads mid-record bytes as the next tag; corrupted bodies in transit.","solutions":["Align client and server versions so both understand the same algorithm tag set (v1: 1=blake3, 2=sha256)","If you operate the server, only emit tag 1 or 2 per record for this protocol version","If corruption is suspected, disable blob packs to fall back to per-blob GETs where each blob is independently digest-verified and resync is impossible to misalign","Capture and hex-dump the offending pack to check whether the stream is merely misaligned (earlier record's size wrong) rather than a genuinely new tag"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.get_blob_pack(&digests, &staging).await {\n    Err(e) if e.to_string().contains(\"invalid digest algorithm\") => {\n        client.disable_blob_packs();\n        fallback_per_blob(&client, &digests) // each blob digest-verified independently\n    }\n    other => other?,\n}","preventionTips":["Server: emit only algorithm tag 1 (blake3) or 2 (sha256) per record on protocol v1","When extending the pack format with new algorithms, bump the protocol major so old clients negotiate away from packs","A misaligned stream usually means an earlier record's size field was wrong — hex-dump the pack before assuming a new tag","Prefer disabling blob packs over retrying: tag errors indicate format mismatch, not transient faults"],"tags":["mise","cache","integrity","blob-pack","wire-format","digest"],"backgroundTag":"invalid-wire-format-tag","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}