{"record":{"id":"13b8880dc40a73ae","repo":"twpayne/chezmoi","slug":"size-mismatch-expected-d-got-d","errorCode":null,"errorMessage":"size mismatch: expected %d, got %d","messagePattern":"size mismatch: expected (.+?), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1689,"sourceCode":"func (s *SourceState) getExternalData(\n\tctx context.Context,\n\texternalRelPath RelPath,\n\texternal *External,\n\toptions *ReadOptions,\n) ([]byte, string, error) {\n\tdata, urlStr, err := s.getExternalDataAndURL(ctx, externalRelPath, external, options)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\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\",","sourceCodeStart":1671,"sourceCodeEnd":1707,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1671-L1707","documentation":"When downloading an external (archive/file), chezmoi verifies the downloaded data length against the declared checksum.size from the external definition. If the byte count differs, this error is appended and the external is rejected, because a size mismatch may indicate a corrupted or tampered download.","triggerScenarios":"len(data) != external.Checksum.Size while verifying a downloaded external in TestFS/NewTar/tarAddEntry paths (sourcestate.go:1689) — the fetched content's byte count differs from the declared size in .chezmoiexternal.","commonSituations":"The upstream project released a new version at the same URL (moving latest), the URL was mistyped, a proxy/mirror truncated the download, or the recorded size was copied from a different release.","solutions":["Re-verify the download URL and update the size (and hashes) to match the current release artifact","Pin the URL to an exact versioned release instead of a 'latest' endpoint","Re-download the artifact yourself, confirm its byte size, and update the external definition"],"exampleFix":"# before\n[\".local/bin/tool\"]\n  type = \"file\"\n  url = \"https://example.com/tool-latest\"\n  size = 1234567\n# after\n[\".local/bin/tool\"]\n  type = \"file\"\n  url = \"https://example.com/tool-1.2.3\"\n  size = 1234890\n  sha256 = \"<hash-of-tool-1.2.3>\"","handlingStrategy":"validation","validationCode":"resp, _ := http.Get(url)\nn, _ := io.Copy(io.Discard, resp.Body)\nif int(n) != declaredSize {\n    fmt.Printf(\"upstream artifact size %d != declared %d; update external definition\\n\", n, declaredSize)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin externals to exact release URLs, never 'latest'","Record sha256 alongside size for every external","Re-checksum artifacts when the upstream release changes"],"tags":["external","checksum","download"],"backgroundTag":"download-size-mismatch","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}