{"record":{"id":"936099baf2adf332","repo":"astrid-runtime/astrid","slug":"immutable-release-manifest-does-not-match-the-chan","errorCode":null,"errorMessage":"immutable release manifest does not match the channel BLAKE3 digest","messagePattern":"immutable release manifest does not match the channel BLAKE3 digest","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/astrid-cli/src/commands/update_channel.rs","lineNumber":570,"sourceCode":"        || kind != \"nightly\"\n        || date.len() != 8\n        || !date.bytes().all(|byte| byte.is_ascii_digit())\n        || NaiveDate::parse_from_str(date, \"%Y%m%d\").is_err()\n        || commit.len() != 40\n        || !commit\n            .bytes()\n            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))\n    {\n        return None;\n    }\n    Some(commit)\n}\n\npub(super) fn verify_release_manifest(\n    bytes: &[u8],\n    pointer: &ChannelPointer,\n) -> anyhow::Result<()> {\n    ensure!(\n        blake3::hash(bytes).to_hex().as_str() == pointer.release.metadata_blake3,\n        \"immutable release manifest does not match the channel BLAKE3 digest\"\n    );\n    let text = std::str::from_utf8(bytes).context(\"release manifest is not UTF-8\")?;\n    let manifest: ReleaseManifest =\n        toml::from_str(text).context(\"release manifest is invalid TOML\")?;\n    ensure!(\n        manifest.schema_version == 1\n            && manifest.kind == \"astrid-release\"\n            && manifest.product == PRODUCT\n            && manifest.repository == REPOSITORY,\n        \"release manifest identity is invalid\"\n    );\n    ensure!(\n        manifest.version == pointer.release.version\n            && manifest.tag == pointer.release.tag\n            && manifest.source_commit == pointer.release.source_commit\n            && manifest.release_workflow_identity == pointer.release.release_workflow_identity,","sourceCodeStart":552,"sourceCodeEnd":588,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/update_channel.rs#L552-L588","documentation":"The BLAKE3 hash of the downloaded release manifest bytes does not equal the metadata_blake3 digest recorded in the signed channel pointer. This is an integrity check: the manifest has been corrupted, replaced, or the pointer is stale.","triggerScenarios":"verify_release_manifest (called from resolve_signed_channel) hashes the fetched manifest bytes and compares against pointer.release.metadata_blake3; mismatch occurs on truncated downloads, a re-published manifest without updating the pointer, or a tampered manifest.","commonSituations":"Proxy/CDN serving a stale or modified manifest; publisher forgot to re-sign the pointer after editing the manifest; disk corruption in the state directory.","solutions":["Re-fetch the channel pointer and manifest to rule out transient corruption","Re-publish the channel so metadata_blake3 matches the current manifest","Check for caching proxies/CDN serving outdated manifests","Clear the local channel state and retry resolution"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"let expected = &pointer.release.metadata_blake3;\nif blake3::hash(bytes).to_hex().as_str() != expected {\n    eprintln!(\"manifest digest mismatch; re-fetch\");\n}","typeGuard":null,"tryCatchPattern":"loop {\n    match fetch_and_verify_manifest(&pointer) {\n        Ok(m) => break m,\n        Err(e) if attempts < 3 => attempts += 1,\n        Err(e) => return Err(e),\n    }\n}","preventionTips":["Always verify hashes before trusting downloaded metadata","Bypass CDNs/proxies when debugging digest mismatches","Re-sign the pointer whenever the manifest changes"],"tags":["integrity","blake3","checksum"],"backgroundTag":"checksum-mismatch","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"}