{"record":{"id":"ec81cd9a82517d8a","repo":"kubernetes/kops","slug":"failed-to-copy-index-v","errorCode":null,"errorMessage":"failed to copy index: %v","messagePattern":"failed to copy index: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/assets/assetcopy/copyimage.go","lineNumber":68,"sourceCode":"\n\toptions := []remote.Option{remote.WithAuthFromKeychain(authn.DefaultKeychain)}\n\n\tdesc, err := remote.Get(sourceRef, options...)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fetching %q: %v\", source, err)\n\t}\n\n\ttargetDesc, err := remote.Get(targetRef, options...)\n\tif err == nil && desc.Digest.String() == targetDesc.Digest.String() {\n\t\tklog.Infof(\"no need to copy image from %v to %v\", sourceRef, targetRef)\n\t\treturn nil\n\t}\n\n\tswitch desc.MediaType {\n\tcase types.OCIImageIndex, types.DockerManifestList:\n\t\t// Handle indexes separately.\n\t\tif err := copyIndex(desc, sourceRef, targetRef, options...); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to copy index: %v\", err)\n\t\t}\n\tdefault:\n\t\t// Assume anything else is an image, since some registries don't set mediaTypes properly.\n\t\tif err := copyImage(desc, sourceRef, targetRef, options...); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to copy image: %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc copyImage(desc *remote.Descriptor, sourceRef name.Reference, targetRef name.Reference, options ...remote.Option) error {\n\tklog.Infof(\"copying image from %v to %v\", sourceRef, targetRef)\n\n\timg, err := desc.Image()\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/assets/assetcopy/copyimage.go#L50-L86","documentation":"The source descriptor's media type was an OCI image index or Docker manifest list, so Run called copyIndex, which fetches the index via desc.ImageIndex() and pushes it with remote.WriteIndex; any failure there is wrapped as \"failed to copy index: %v\". Typical causes are errors reading child manifests from the source or errors writing the index (and its children) to the target registry.","triggerScenarios":"The source image is a multi-arch manifest list (e.g. official kubernetes images); desc.ImageIndex() fails to fetch child manifests from the source, or remote.WriteIndex fails pushing to the target because of auth (401/403), missing repository (need to create it), quota, unsupported media types, or network interruption mid-push.","commonSituations":"Copying multi-arch images into a private registry whose credentials are missing (unauthorized push); target registry rejects a child manifest's media type or size; interrupted push leaves the index incomplete and subsequent runs fail; target registry requires the repository to exist first (e.g. some Harbor setups); disk/quota limits on the private registry.","solutions":["Verify push credentials for the TARGET registry (`docker login <target-registry>`, check keychain/credential helper).","Retry the copy; remote.WriteIndex retries internally per-blob but transient network failures still surface — re-running resumes.","Check the target registry's media-type/size limits and that the repository is allowed to be created.","Inspect the inner error (%v) for the specific blob/manifest that failed and verify it exists on the source with `crane manifest`."],"exampleFix":"// before\n$ kops ... # failed to copy index: writing manifest: unauthorized: authentication required\n// after\n$ docker login myregistry.example.com\n$ kops replace -f cluster.yaml && kops update cluster ... # re-run asset copy","handlingStrategy":"retry","validationCode":"if out, err := exec.Command(\"crane\", \"validate\", \"--remote\", sourceImage).CombinedOutput(); err != nil {\n\treturn fmt.Errorf(\"multi-arch source %q not fully pullable: %v: %s\", sourceImage, err, out)\n}\nif err := checkPushAccess(targetRegistry); err != nil {\n\treturn err\n}","typeGuard":null,"tryCatchPattern":"err := e.Run()\nfor i := 0; i < 3 && err != nil; i++ {\n\tif !strings.Contains(err.Error(), \"failed to copy index\") {\n\t\tbreak\n\t}\n\ttime.Sleep(time.Duration(1<<i) * time.Second)\n\tif err = e.Run(); err == nil {\n\t\tbreak\n\t}\n}","preventionTips":["Confirm push credentials for the target registry before bulk multi-arch copies.","Pre-create the target repository if your registry requires it (Harbor/ECR policies).","Ensure stable network to the target registry; large index copies are long and interruption-prone.","Check target registry media-type and size limits for manifest lists beforehand."],"tags":["container-image","registry","push","multi-arch"],"backgroundTag":"image-push-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}