{"record":{"id":"780d3fac038314ac","repo":"kubernetes/kops","slug":"error-adding-needs-update-label-v","errorCode":null,"errorMessage":"error adding needs-update label: %v","messagePattern":"error adding needs-update label: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/addon.go","lineNumber":226,"sourceCode":"\t\tmerr = multierr.Append(merr, fmt.Errorf(\"error pruning manifest: %w\", pruneError))\n\t}\n\n\tif applyError != nil && pruneError == nil {\n\t\t// If we failed to apply, but not prune, we should try to apply again\n\t\tif err := applier.Apply(ctx, data); err != nil {\n\t\t\tmerr = multierr.Append(merr, fmt.Errorf(\"error applying update after prune: %w\", err))\n\t\t} else {\n\t\t\t// If we succeeded to apply after prune, clear the errors\n\t\t\tmerr = nil\n\t\t}\n\t}\n\n\tif merr != nil {\n\t\treturn fmt.Errorf(\"error updating addon from %q: %w\", manifestURL, merr)\n\t}\n\n\tif err := a.AddNeedsUpdateLabel(ctx, k8sClient, required); err != nil {\n\t\treturn fmt.Errorf(\"error adding needs-update label: %v\", err)\n\t}\n\n\tchannel := a.buildChannel()\n\terr = channel.SetInstalledVersion(ctx, k8sClient, a.ChannelVersion())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error applying annotation to record addon installation: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc (a *Addon) AddNeedsUpdateLabel(ctx context.Context, k8sClient kubernetes.Interface, required *AddonUpdate) error {\n\tif required.ExistingVersion != nil {\n\t\tif a.Spec.NeedsRollingUpdate != \"\" {\n\t\t\terr := a.patchNeedsUpdateLabel(ctx, k8sClient)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error patching needs-update label: %v\", err)\n\t\t\t}\n\t\t}","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/addon.go#L208-L244","documentation":"updateAddon in channels/pkg/channels/addon.go wraps any failure from AddNeedsUpdateLabel after the addon manifest was successfully applied. This happens when patching the 'kops.k8s.io/needs-update' annotation onto cluster nodes fails (node List or node Patch API error). The addon resources are applied but the rolling-update signal was not recorded, so node upgrades may not be triggered.","triggerScenarios":"EnsureUpdated -> updateAddon with an addon whose Spec.NeedsRollingUpdate is set and whose ExistingVersion is non-nil (an upgrade, not a fresh install), and patchNeedsUpdateLabel fails: node List with a role label selector fails, or a node strategic-merge Patch fails (RBAC denial, node deleted mid-loop, API server unreachable).","commonSituations":"Running 'kops update cluster' with an identity lacking patch permission on nodes; an addon (e.g. CNI) declares needsRollingUpdate while nodes are being deleted/resized concurrently; temporary API server outage during the upgrade.","solutions":["Verify the caller has RBAC rights to list and patch core/v1 Nodes.","Re-run 'kops update cluster' / apply: the addon manifest already applied and the label patch is idempotent.","Check API server connectivity and that target nodes still exist; reconcile node groups.","If the addon does not actually require a rolling update, remove needsRollingUpdate from its channel spec."],"exampleFix":"// before\nif err := a.AddNeedsUpdateLabel(ctx, k8sClient, required); err != nil {\n\treturn fmt.Errorf(\"error adding needs-update label: %v\", err)\n}\n// after\nif err := a.AddNeedsUpdateLabel(ctx, k8sClient, required); err != nil {\n\tklog.Warningf(\"needs-update label not applied (addon manifest already applied): %v\", err)\n}","handlingStrategy":"retry","validationCode":"// pre-check node access before running the update\nnodes, err := k8sClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{LabelSelector: \"node-role.kubernetes.io/node=\"})\nif err != nil {\n\treturn fmt.Errorf(\"cannot list nodes, needs-update patching will fail: %w\", err)\n}\n_ = nodes","typeGuard":null,"tryCatchPattern":"err := addon.EnsureUpdated(ctx, k8sClient, vfsContext, pruner, applier)\nif err != nil && strings.Contains(err.Error(), \"error adding needs-update label\") {\n\t// manifest already applied; degrade gracefully and retry the label step\n\tklog.Warningf(\"addon applied but rolling-update label not set: %v\", err)\n}","preventionTips":["Grant nodes list+patch RBAC to the identity running kops.","Re-run update cluster after transient API failures; label patching is idempotent.","Only set needsRollingUpdate in addon specs that truly require node restarts.","Avoid deleting/scaling down nodes while kops update runs."],"tags":["kubernetes","rbac","node-labels","rolling-update"],"backgroundTag":"needs-update-label-patch-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"}