rpm-local repodata: intermittent checksum mismatch (repomd vs primary) breaks dnf #117
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
dnf installfrom an rpm-local repo (rpm-internal) intermittently fails with a repodata checksum mismatch —repomd.xmladvertises aprimary.xml.gzsha256, but the bytes served for that content-addressed file hash to something else. Observed in the wild:The repodata is regenerated per request (not stored), and the API runs 2 replicas with no session affinity. So the
repomd.xmlfetch and the subsequentprimary.xml.gzfetch can see different bytes when either:ORDER BY, or gzip mtime/OS bytes).Retried immediately, the hashes matched — so it is intermittent, not persistent. It affects every rpm-local consumer via
dnf. The deb/apk local providers likely share the class (Release→Packages/Packages.gzchecksums) under the same 2-replica deployment.Workaround: install the RPM directly by URL (
dnf install <.../Packages/<file>.rpm>), which bypasses repodata.Proposal
Make the served repodata set internally consistent for any fetch sequence:
repomd+primary/filelists/other) from ONE DB snapshot with deterministic ordering (explicitORDER BYon the metadata query) and zero-mtime gzip, so it is byte-identical across replicas and requests.repomd.xmland its referenced hashed files always agree; evict on upload/delete.Release↔Packages/APKINDEXgeneration.Acceptance
dnf makecache/installagainstrpm-internalacross many requests — including concurrent with an upload — never produce a checksum mismatch.repomd.xmlprimary/filelists/other sha256 equals the sha256 of the bytes actually served at those paths, verified against both replicas.aptagainst a deb-local repo (Release ↔ Packages) and forapk(APKINDEX).Resolved across three PRs — local generated repodata is now byte-identical across replicas and regenerations, so the advertised checksums always match the served content-addressed bytes:
<time>/repomdrevision from persistedcreated_atinstead oftime.Now(); total-orderORDER BY; pin gzip header.ReleaseDate:from newestcreated_at; pin apkAPKINDEX.tar.gztar ModTime; total-orderORDER BYon both.Root cause was a wall-clock timestamp (
time.Now()) embedded inside the content-addressed gzippedprimary.xml; the deb/apk paths got the same determinism guarantee plus regression tests asserting advertised-checksum == served-bytes.Shipped in v3.10.1. (Remote repos were never affected — they proxy upstream's content-addressed repodata verbatim.)