{"record":{"id":"504af5d91646f42c","repo":"kubernetes/kops","slug":"duplicate-image-task-q","errorCode":null,"errorMessage":"duplicate image task %q","messagePattern":"duplicate image task %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/nodeup/command.go","lineNumber":354,"sourceCode":"\tloader.Builders = append(loader.Builders, &networking.KuberouterBuilder{NodeupModelContext: modelContext})\n\n\tloader.Builders = append(loader.Builders, &model.BootstrapClientBuilder{NodeupModelContext: modelContext})\n\ttaskMap, err := loader.Build()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building loader: %v\", err)\n\t}\n\n\tfor _, image := range nodeupConfig.Images[architecture] {\n\t\tif len(image.Sources) == 0 {\n\t\t\treturn fmt.Errorf(\"image has no sources: %v\", image)\n\t\t}\n\t\tu, err := url.Parse(image.Sources[0])\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid image source URL %q: %w\", image.Sources[0], err)\n\t\t}\n\t\tkey := \"SideloadImage/\" + path.Base(u.Path)\n\t\tif _, ok := taskMap[key]; ok {\n\t\t\treturn fmt.Errorf(\"duplicate image task %q\", key)\n\t\t}\n\t\ttaskMap[key] = &nodetasks.LoadImageTask{\n\t\t\tSources: image.Sources,\n\t\t\tHash:    image.Hash,\n\t\t}\n\t}\n\n\tvar target fi.NodeupTarget\n\n\tswitch c.Target {\n\tcase \"direct\":\n\t\ttarget = &local.LocalTarget{\n\t\t\tCacheDir: c.CacheDir,\n\t\t\tCloud:    cloud,\n\t\t}\n\tcase \"dryrun\":\n\t\tassetBuilder := assets.NewAssetBuilder(vfs.Context, nil, false)\n\t\ttarget = fi.NewNodeupDryRunTarget(assetBuilder, out)","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/nodeup/command.go#L336-L372","documentation":"Run() keys each sideload image task as \"SideloadImage/\" + the base name of the source URL path. If a task with that key already exists in the taskMap, nodeup refuses to overwrite it and errors with \"duplicate image task\". This prevents two LoadImageTasks fighting over the same image file, usually caused by duplicate image entries in the config.","triggerScenarios":"Two or more entries in nodeupConfig.Images[architecture] whose first source URL has the same path base (e.g. same filename from different registries), producing the same SideloadImage/<name> key.","commonSituations":"The same image listed twice (once from registry.k8s.io, once from a mirror) in containerd images config; merging cluster specs that duplicated an image entry; case/name collisions between custom and default images.","solutions":["De-duplicate the image list in nodeupConfig.Images[architecture] so each source filename appears once","If a mirror variant is needed, rename the path segment so base(u.Path) differs (e.g. include a subdirectory or distinct filename)","Regenerate the config with `kops update cluster` after cleaning up custom image overrides in the cluster spec","Check that any config merge/patch tooling is not appending the same image twice"],"exampleFix":"// before: two entries whose sources both end in /pause:3.9 -> SideloadImage/pause:3.9 twice\n// after: keep one entry or differentiate paths\n// \"sources\": [\"https://registry.k8s.io/pause:3.9\"]  // remove the duplicate mirror entry","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, img := range nodeupConfig.Images[arch] {\n    u, _ := url.Parse(img.Sources[0])\n    key := \"SideloadImage/\" + path.Base(u.Path)\n    if seen[key] {\n        return fmt.Errorf(\"duplicate image %s in config\", key)\n    }\n    seen[key] = true\n}","typeGuard":null,"tryCatchPattern":"if err := nodeupCmd.Run(ctx); err != nil {\n    if strings.Contains(err.Error(), \"duplicate image task\") {\n        log.Fatalf(\"de-duplicate images in NodeupConfig: %v\", err)\n    }\n    return err\n}","preventionTips":["De-duplicate image lists when merging or patching cluster specs","Give mirror copies distinct path segments if both are needed","Run `kops update cluster --target dryrun` and review the rendered images map","Automate a pre-flight dup check on custom image overrides"],"tags":["nodeup","images","duplicate","task-generation"],"backgroundTag":"duplicate-task-key","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}