{"record":{"id":"4b7b95d544216d3f","repo":"twpayne/chezmoi","slug":"md5-mismatch-expected-s-got-s","errorCode":null,"errorMessage":"MD5 mismatch: expected %s, got %s","messagePattern":"MD5 mismatch: expected (.+?), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1700,"sourceCode":"\tvar errs []error\n\n\tif external.Checksum.Size != 0 {\n\t\tif external.Checksum.SHA256 == nil && external.Checksum.SHA384 == nil && external.Checksum.SHA512 == nil {\n\t\t\ts.warnFunc(\"%s: warning: insecure size check without secure hash will be removed\\n\", externalRelPath)\n\t\t}\n\t\tif len(data) != external.Checksum.Size {\n\t\t\terr := fmt.Errorf(\"size mismatch: expected %d, got %d\", external.Checksum.Size, len(data))\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif external.Checksum.MD5 != nil {\n\t\ts.warnFunc(\n\t\t\t\"%s: warning: insecure MD5 checksum will be removed, use a secure hash like SHA256 instead\\n\",\n\t\t\texternalRelPath,\n\t\t)\n\t\tif gotMD5Sum := md5Sum(data); !bytes.Equal(gotMD5Sum, external.Checksum.MD5) {\n\t\t\terr := fmt.Errorf(\"MD5 mismatch: expected %s, got %s\", external.Checksum.MD5, hex.EncodeToString(gotMD5Sum))\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif external.Checksum.RIPEMD160 != nil {\n\t\ts.warnFunc(\n\t\t\t\"%s: warning: insecure RIPEMD-160 checksum will be removed, use a secure hash like SHA256 instead\\n\",\n\t\t\texternalRelPath,\n\t\t)\n\t\tif gotRIPEMD160Sum := ripemd160Sum(data); !bytes.Equal(gotRIPEMD160Sum, external.Checksum.RIPEMD160) {\n\t\t\tformat := \"RIPEMD-160 mismatch: expected %s, got %s\"\n\t\t\terr := fmt.Errorf(format, external.Checksum.RIPEMD160, hex.EncodeToString(gotRIPEMD160Sum))\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif external.Checksum.SHA1 != nil {\n\t\ts.warnFunc(","sourceCodeStart":1682,"sourceCodeEnd":1718,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1682-L1718","documentation":"chezmoi downloads external file data and verifies it against checksums declared in the source state's external entry. When the MD5 checksum configured in .chezmoiexternal does not match the MD5 of the downloaded bytes, the computed and expected digests are formatted into this error and accumulated. MD5 is deprecated for security, so chezmoi also warns that support will be removed; use SHA256 instead.","triggerScenarios":"An external entry in .chezmoiexternal with a checksum.md5 field is fetched; md5Sum(data) differs from external.Checksum.MD5. Happens when the upstream file changed since the checksum was recorded, or the checksum was copy-pasted/truncated incorrectly.","commonSituations":"Pinning a GitHub release tarball by MD5 that upstream re-released; hand-computing the checksum on a different file; proxy or mirror serving altered content; declaring an MD5 checksum against a file that is actually SHA256-encoded hex.","solutions":["Recompute the correct checksum: curl the URL and run md5sum, then update checksum.md5 in .chezmoiexternal.","Prefer a secure hash: compute sha256sum and declare checksum.sha256 instead (MD5 support is being removed).","If upstream is genuinely volatile, drop the checksum field entirely (losing integrity verification).","Check the download path (proxy/mirror) is serving the exact bytes you hashed."],"exampleFix":"// before (.chezmoiexternal.toml)\n[.tmux.conf]\n  type = \"file\"\n  url = \"https://example.com/tmux.conf\"\n  checksum.md5 = \"abcd1234\"\n// after\n  # md5sum tmux.conf  -> e3b0c44298fc1c149afbf4c8996fb924\n  checksum.sha256 = \"<sha256 of file>\"","handlingStrategy":"validation","validationCode":"# Verify the checksum before chezmoi does:\ncurl -sL \"https://example.com/artifact\" | md5sum\n# Compare with checksum.md5 in .chezmoiexternal; prefer:\ncurl -sL \"https://example.com/artifact\" | sha256sum","typeGuard":null,"tryCatchPattern":"// Run `chezmoi apply --dry-run` (or `chezmoi diff`) and treat any output containing\n// 'MD5 mismatch' as a hard stop; fix .chezmoiexternal before applying.\nif err := run(\"chezmoi\", \"apply\", \"--dry-run\"); strings.Contains(err.Error(), \"mismatch\") {\n    return fmt.Errorf(\"external checksum drift: %w\", err)\n}","preventionTips":["Always pin checksum.sha256, not MD5 (MD5 is insecure and slated for removal).","Generate checksums in CI directly from the release artifact, never by hand.","Pin URLs to immutable release assets, not moving 'latest' links.","Run chezmoi apply --dry-run in CI to catch checksum drift early."],"tags":["checksum","external","integrity","md5"],"backgroundTag":"checksum-mismatch","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}