{"record":{"id":"42ba8766f461a92e","repo":"twpayne/chezmoi","slug":"sha384-mismatch-expected-s-got-s","errorCode":null,"errorMessage":"SHA384 mismatch: expected %s, got %s","messagePattern":"SHA384 mismatch: expected (.+?), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1738,"sourceCode":"\t\t\texternalRelPath,\n\t\t)\n\t\tif gotSHA1Sum := sha1Sum(data); !bytes.Equal(gotSHA1Sum, external.Checksum.SHA1) {\n\t\t\terr := fmt.Errorf(\"SHA1 mismatch: expected %s, got %s\", external.Checksum.SHA1, hex.EncodeToString(gotSHA1Sum))\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif external.Checksum.SHA256 != nil {\n\t\tif gotSHA256Sum := sha256.Sum256(data); !bytes.Equal(gotSHA256Sum[:], external.Checksum.SHA256) {\n\t\t\tformat := \"SHA256 mismatch: expected %s, got %s\"\n\t\t\terr := fmt.Errorf(format, external.Checksum.SHA256, hex.EncodeToString(gotSHA256Sum[:]))\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif external.Checksum.SHA384 != nil {\n\t\tif gotSHA384Sum := sha384Sum(data); !bytes.Equal(gotSHA384Sum, external.Checksum.SHA384) {\n\t\t\terrs = append(errs, fmt.Errorf(\"SHA384 mismatch: expected %s, got %s\",\n\t\t\t\texternal.Checksum.SHA384, hex.EncodeToString(gotSHA384Sum)))\n\t\t}\n\t}\n\n\tif external.Checksum.SHA512 != nil {\n\t\tif gotSHA512Sum := sha512Sum(data); !bytes.Equal(gotSHA512Sum, external.Checksum.SHA512) {\n\t\t\terrs = append(errs, fmt.Errorf(\"SHA512 mismatch: expected %s, got %s\",\n\t\t\t\texternal.Checksum.SHA512, hex.EncodeToString(gotSHA512Sum)))\n\t\t}\n\t}\n\n\tif len(errs) != 0 {\n\t\treturn nil, urlStr, fmt.Errorf(\"%s: %w\", externalRelPath, errors.Join(errs...))\n\t}\n\n\tif external.Encrypted {\n\t\tdata, err = s.encryption.Decrypt(data)\n\t\tif err != nil {","sourceCodeStart":1720,"sourceCodeEnd":1756,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1720-L1756","documentation":"The SHA384 branch of external checksum verification: if external.Checksum.SHA384 is set and sha384Sum(data) differs, the formatted mismatch error is appended to errs. It is later surfaced wrapped by the external's relative path via errors.Join.","triggerScenarios":"External entry declares checksum.sha384; downloaded bytes hash differently than the pinned SHA384 digest.","commonSituations":"Artifact updated upstream after pinning; checksum generated on a different file or from base64 vs hex confusion; truncated digest in the config.","solutions":["Recompute with openssl dgst -sha384 <file> (or curl -sL <url> | openssl dgst -sha384) and update checksum.sha384.","Prefer checksum.sha256, the conventionally supported secure option.","Ensure the digest is full-length hex (96 hex chars for SHA384).","Verify the download pipeline (proxy/mirror) isn't altering content."],"exampleFix":"// before\nchecksum.sha384 = \"<old digest>\"\n// after\nchecksum.sha384 = \"<freshly computed sha384 of the artifact>\"","handlingStrategy":"validation","validationCode":"openssl dgst -sha384 <file>  # or: curl -sL \"$URL\" | openssl dgst -sha384\n# Must yield 96 hex chars matching checksum.sha384.","typeGuard":null,"tryCatchPattern":"out, err := exec.Command(\"chezmoi\", \"apply\").CombinedOutput()\nif err != nil && strings.Contains(string(out), \"SHA384 mismatch\") {\n    return errors.New(\"recompute checksum.sha384 from the current artifact\")\n}","preventionTips":["Validate digest format (96 hex chars) before committing it.","Prefer sha256 as the single checksum per external.","Pin URLs to immutable artifacts."],"tags":["checksum","external","integrity","sha384"],"backgroundTag":"checksum-mismatch","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}