{"record":{"id":"f6fa6762dc29c92a","repo":"kubernetes/kops","slug":"different-sources-for-same-image-target-s-s-vs","errorCode":null,"errorMessage":"different sources for same image target %s: %s vs %s","messagePattern":"different sources for same image target (.+?): (.+?) vs (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/assets/assetcopy/copy.go","lineNumber":50,"sourceCode":"\ntype assetTask interface {\n\tRun() error\n}\n\nfunc Copy(imageAssets []*assets.ImageAsset, fileAssets []*assets.FileAsset, vfsContext *vfs.VFSContext, cluster *kops.Cluster) error {\n\ttasks := map[string]assetTask{}\n\n\tfor _, imageAsset := range imageAssets {\n\t\tif imageAsset.DownloadLocation != imageAsset.CanonicalLocation {\n\t\t\tcopyImageTask := &CopyImage{\n\t\t\t\tName:        imageAsset.DownloadLocation,\n\t\t\t\tSourceImage: imageAsset.CanonicalLocation,\n\t\t\t\tTargetImage: imageAsset.DownloadLocation,\n\t\t\t}\n\n\t\t\tif existing, ok := tasks[copyImageTask.Name]; ok {\n\t\t\t\tif existing.(*CopyImage).SourceImage != copyImageTask.SourceImage {\n\t\t\t\t\treturn fmt.Errorf(\"different sources for same image target %s: %s vs %s\", copyImageTask.Name, copyImageTask.SourceImage, existing.(*CopyImage).SourceImage)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttasks[copyImageTask.Name] = copyImageTask\n\t\t}\n\t}\n\n\tfor _, fileAsset := range fileAssets {\n\t\tif fileAsset.DownloadURL.String() != fileAsset.CanonicalURL.String() {\n\t\t\tcopyFileTask := &CopyFile{\n\t\t\t\tName:       fileAsset.CanonicalURL.String(),\n\t\t\t\tTargetFile: fileAsset.DownloadURL.String(),\n\t\t\t\tSourceFile: fileAsset.CanonicalURL.String(),\n\t\t\t\tSHA:        fileAsset.SHAValue.Hex(),\n\t\t\t\tVFSContext: vfsContext,\n\t\t\t\tCluster:    cluster,\n\t\t\t}\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/assets/assetcopy/copy.go#L32-L68","documentation":"While building the copy task set, assetcopy deduplicates tasks by task name (the image target). If two image assets map to the same target name but have different CanonicalLocation sources, copying would non-deterministically pick one, so Copy fails fast with this error instead of producing a corrupt mirror.","triggerScenarios":"Two ImageAssets whose DownloadLocation (task name/target) collide while their CanonicalLocation values differ, both processed in one Copy call from the AssetBuilder.","commonSituations":"Image tags pointing at the same local target name but resolved from different registries (e.g. registry.k8s.io vs a mirror); an image retagged/relocated between runs so assets built from mixed versions disagree; customized asset file overrides mapping two upstream images to one target.","solutions":["Ensure each distinct source image gets a unique target name, or normalize the CanonicalLocation so duplicates agree","Pin image versions/tags so all assets resolve to the same source for a given target","Refresh the asset build from a consistent source (single registry/repo) so mixed-location assets are not combined","If using image mirrors/overrides in the cluster spec, verify no two entries collide on the same target"],"exampleFix":"// before\n// two assets: nginx:1.25 from registry.k8s.io and from mirror.example rewritten to same target\n// after\n// use distinct targets or a single canonical source:\n// target: my-registry.io/nginx:1.25 sourced only from registry.k8s.io/nginx:1.25","handlingStrategy":"validation","validationCode":"seen := map[string]string{}\nfor _, a := range imageAssets {\n\ttarget := a.DownloadLocation\n\tif prev, ok := seen[target]; ok && prev != a.CanonicalLocation {\n\t\treturn fmt.Errorf(\"pre-check: image target %s has conflicting sources %s vs %s\", target, prev, a.CanonicalLocation)\n\t}\n\tseen[target] = a.CanonicalLocation\n}","typeGuard":"func imageSourcesConsistent(assets []ImageAsset) bool {\n\tseen := map[string]string{}\n\tfor _, a := range assets {\n\t\tif p, ok := seen[a.DownloadLocation]; ok && p != a.CanonicalLocation {\n\t\t\treturn false\n\t\t}\n\t\tseen[a.DownloadLocation] = a.CanonicalLocation\n\t}\n\treturn true\n}","tryCatchPattern":"if err := copy.Run(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"different sources for same image target\") {\n\t\treturn fmt.Errorf(\"asset config bug: %w — pin image versions so one target maps to one source\", err)\n\t}\n\treturn err\n}","preventionTips":["Pin image tags/digests so all builds resolve to one canonical source","Use a single image registry/mirror configuration per cluster","Check image overrides in the cluster spec for target collisions","Regenerate assets from one consistent kOps version"],"tags":["assets","images","deduplication"],"backgroundTag":"asset-source-mismatch","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"}