{"record":{"id":"240eebf5665cba19","repo":"docker/cli","slug":"internal-digest-mismatch-for-s-expected-s-got","errorCode":null,"errorMessage":"internal digest mismatch for %s: expected %s, got %s","messagePattern":"internal digest mismatch for (.+?): expected (.+?), got (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/manifest/push.go","lineNumber":216,"sourceCode":"\t// with the registry - if we haven't preserved the raw content.\n\t//\n\t// This is necessary because our previous internal storage format did not\n\t// preserve whitespace. If we don't have the newer format present, we can\n\t// attempt the reconstruction like before, but explicitly error if the\n\t// reconstruction failed!\n\tswitch {\n\tcase imageManifest.SchemaV2Manifest != nil:\n\t\tdt := imageManifest.Raw\n\t\tif len(dt) == 0 {\n\t\t\tdt, err = json.MarshalIndent(imageManifest.SchemaV2Manifest, \"\", \"   \")\n\t\t\tif err != nil {\n\t\t\t\treturn mountRequest{}, err\n\t\t\t}\n\t\t}\n\n\t\tdig := imageManifest.Descriptor.Digest\n\t\tif dig2 := dig.Algorithm().FromBytes(dt); dig != dig2 {\n\t\t\treturn mountRequest{}, fmt.Errorf(\"internal digest mismatch for %s: expected %s, got %s\", imageManifest.Ref, dig, dig2)\n\t\t}\n\n\t\tvar manifest schema2.DeserializedManifest\n\t\tif err = manifest.UnmarshalJSON(dt); err != nil {\n\t\t\treturn mountRequest{}, err\n\t\t}\n\t\timageManifest.SchemaV2Manifest = &manifest\n\tcase imageManifest.OCIManifest != nil:\n\t\tdt := imageManifest.Raw\n\t\tif len(dt) == 0 {\n\t\t\tdt, err = json.MarshalIndent(imageManifest.OCIManifest, \"\", \"  \")\n\t\t\tif err != nil {\n\t\t\t\treturn mountRequest{}, err\n\t\t\t}\n\t\t}\n\n\t\tdig := imageManifest.Descriptor.Digest\n\t\tif dig2 := dig.Algorithm().FromBytes(dt); dig != dig2 {","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/manifest/push.go#L198-L234","documentation":"Returned by `buildPutManifestRequest` (push.go:214-217) in the schema2 path. The CLI reconstructs the manifest bytes (using stored Raw, or re-marshaling with 3-space indent) and recomputes the digest; if it differs from the stored Descriptor.Digest, the internal storage is inconsistent and push is aborted to avoid uploading a manifest whose digest wouldn't match. This guards against the older storage format that didn't preserve raw bytes.","triggerScenarios":"Manifest list created by an older Docker CLI that didn't preserve `Raw` bytes, then pushed by a newer CLI — the re-marshaled indentation produces a different SHA. Also triggered by manual edits to the local manifest store.","commonSituations":"CLI upgrade across the storage-format boundary, or a corrupt local manifest cache.","solutions":["Re-create the manifest list with the current CLI so Raw bytes are preserved: delete and `docker manifest create` again.","Clear the local manifest store and rebuild from registry sources.","Ensure both create and push use the same (recent) CLI version.","Annotate or amend the list to force re-serialization."],"exampleFix":"# before\n# list created by old CLI; push now fails digest check\ndocker manifest push mylist\n# after\nrm -rf ~/.local/share/docker/manifests/<list>\ndocker manifest create mylist img1 img2   # re-create with current CLI\ndocker manifest push mylist","handlingStrategy":"validation","validationCode":"// before pushing, verify schema2 digest parity\nfor _, m := range manifests {\n    if m.SchemaV2Manifest == nil { continue }\n    dt := m.Raw\n    if len(dt) == 0 { dt, _ = json.MarshalIndent(m.SchemaV2Manifest, \"\", \"   \") }\n    if d2 := m.Descriptor.Digest.Algorithm().FromBytes(dt); m.Descriptor.Digest != d2 {\n        return fmt.Errorf(\"member %s digest mismatch; recreate the list with current CLI\", m.Ref)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := runPush(ctx, cli, opts); err != nil {\n    if strings.Contains(err.Error(), \"internal digest mismatch\") {\n        return recreateListAndPush(targetRef) // rebuild with preserved Raw bytes\n    }\n    return err\n}","preventionTips":["Use the same recent CLI version for create and push.","Recreate old lists to preserve Raw bytes.","Never manually edit the local manifest store."],"tags":["manifest","push","digest","data-integrity","schema2","storage-format","docker-cli"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}