{"record":{"id":"8fabee0c2eea3471","repo":"kubernetes/kops","slug":"error-patching-needs-update-label-v","errorCode":null,"errorMessage":"error patching needs-update label: %v","messagePattern":"error patching needs-update label: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/addon.go","lineNumber":242,"sourceCode":"\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}\n\t}\n\treturn nil\n}\n\nfunc (a *Addon) patchNeedsUpdateLabel(ctx context.Context, k8sClient kubernetes.Interface) error {\n\tklog.Infof(\"addon %v wants to update %v nodes\", a.Name, a.Spec.NeedsRollingUpdate)\n\tselector := \"\"\n\tswitch a.Spec.NeedsRollingUpdate {\n\tcase api.NeedsRollingUpdateControlPlane:\n\t\tselector = \"node-role.kubernetes.io/master=\"\n\tcase api.NeedsRollingUpdateWorkers:\n\t\tselector = \"node-role.kubernetes.io/node=\"\n\t}\n\n\tannotationPatch := &annotationPatch{Metadata: annotationPatchMetadata{Annotations: map[string]string{\n\t\t\"kops.k8s.io/needs-update\": \"\",","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/addon.go#L224-L260","documentation":"AddNeedsUpdateLabel wraps the error from patchNeedsUpdateLabel, which lists nodes matching a role selector and patches a 'kops.k8s.io/needs-update' annotation onto each. It only runs when the addon is an upgrade (ExistingVersion != nil) and Spec.NeedsRollingUpdate is set. Failure means node rolling updates for this addon change will not be triggered.","triggerScenarios":"Called from updateAddon during an addon upgrade where the channel spec declares needsRollingUpdate. patchNeedsUpdateLabel fails on: node List with selector 'node-role.kubernetes.io/master=' or '=node' (RBAC, API error), or per-node strategic-merge Patch (node NotFound mid-loop, forbidden).","commonSituations":"IAM/in-cluster RBAC missing nodes patch rights; addon upgrade that requires node restarts while an autoscaler removes nodes; clusters whose node labels differ from the hard-coded selectors so zero nodes match (no error, but no rolling update).","solutions":["Grant the executing identity RBAC permission to list and patch core/v1 Nodes.","Retry the operation; the patch loop is idempotent.","If nodes were deleted concurrently, rerun after the node group stabilizes.","Verify node-role.kubernetes.io labels exist on your nodes for the configured needsRollingUpdate value."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"_, err := k8sClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{LabelSelector: \"node-role.kubernetes.io/node=\"})\nif err != nil {\n\treturn fmt.Errorf(\"cannot list nodes for needs-update annotation: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := a.AddNeedsUpdateLabel(ctx, k8sClient, required)\nif err != nil {\n\t// safe to retry: strategic-merge patch is idempotent\n\tretryWithBackoff(3, func() error { return a.AddNeedsUpdateLabel(ctx, k8sClient, required) })\n}","preventionTips":["Ensure RBAC allows nodes/list and nodes/patch.","Confirm nodes carry node-role.kubernetes.io labels matching needsRollingUpdate.","Retry after node-group churn settles.","Don't set needsRollingUpdate on addons that don't need node restarts."],"tags":["kubernetes","nodes","patch","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"}