CHW-2305 ChecksumMismatch
artifact checksum mismatch: upstream-declared hash disagrees with downloaded bytes; inspect the X-Chainsaw-Checksum-Mismatch header or raise CHAINSAW_CHECKSUM_MODE=log if this is a known-false-posi…
Default message: artifact checksum mismatch: upstream-declared hash disagrees with downloaded bytes; inspect the X-Chainsaw-Checksum-Mismatch header or raise CHAINSAW_CHECKSUM_MODE=log if this is a known-false-positive mirror
HTTP status:403(client)
Reason:CHECKSUM_MISMATCH
Problem. A download was refused because the artifact’s computed
hash did not match the registry-declared hash. Cause. The proxy
re-hashed the bytes and detected an upstream / network disagreement;
under CHAINSAW_CHECKSUM_MODE=quarantine (the default) or block
the request fails. The response carries
X-Chainsaw-Checksum-Mismatch: <ecosystem>/<declared>/<actual> so
operators can audit the disagreement without re-downloading. The
declared hash always comes from registry metadata fetched separately
from the artifact, for the exact file downloaded: Maven/Gradle
.sha256/.sha512/.sha1/.md5 sidecars, the cargo sparse-index
cksum, the NuGet catalog leaf’s packageHash (base64 SHA-512), the
RubyGems v2 version sha (.gem only; .gemspec.rz publishes none).
When no declared hash can be found the download is served and counted
in chainsaw_checksum_unavailable_total; it is never refused for that. The
refused copy is always removed from the serve cache (until 2026-10-21
quarantine left it there, and the retry was served it from cache).
Under block nothing is kept and the next request re-fetches and is
verified again. Under quarantine the exact refused bytes and their
digests are held in a quarantine store no download can read, and that
file is refused on every request until the held copy is released with
DELETE /api/repos/{repo}/packages/{pkg}/versions/{v}/quarantine (see
“Quarantine and release” in the enforcement and policy guide).
Fix. Inspect the header to confirm the mismatch, re-fetch from a
healthy mirror, or set CHAINSAW_CHECKSUM_MODE=log if this is a
known-false-positive mirror. HTTP 403 — a checksum mismatch is a policy
decision (“do not serve a tampered artifact”), not a transient
availability problem, so it is terminal and CI runners must not retry it.