{"record":{"id":"b567932bf5623b05","repo":"kubernetes/kops","slug":"error-applying-annotation-to-namespace-v","errorCode":null,"errorMessage":"error applying annotation to namespace: %v","messagePattern":"error applying annotation to namespace: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/channel_version.go","lineNumber":209,"sourceCode":"\t\treturn fmt.Errorf(\"error querying namespace %q: %v\", c.Namespace, err)\n\t}\n\n\tvalue, err := version.Encode()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tannotationPatch := &annotationPatch{Metadata: annotationPatchMetadata{Annotations: map[string]string{c.AnnotationName(): value}}}\n\tannotationPatchJSON, err := json.Marshal(annotationPatch)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building annotation patch: %v\", err)\n\t}\n\n\tklog.V(2).Infof(\"sending patch: %q\", string(annotationPatchJSON))\n\n\t_, err = k8sClient.CoreV1().Namespaces().Patch(ctx, c.Namespace, types.StrategicMergePatchType, annotationPatchJSON, metav1.PatchOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error applying annotation to namespace: %v\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":191,"sourceCodeEnd":213,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/channel_version.go#L191-L213","documentation":"After building the patch, SetInstalledVersion sends a StrategicMergePatch to the namespace to set the version annotation. If the Patch API call fails, the client error is wrapped as 'error applying annotation to namespace'. The version was not recorded even though the namespace exists.","triggerScenarios":"Calling Channel.SetInstalledVersion when the caller lacks patch permission on namespaces (Forbidden), the namespace was deleted between the GET and PATCH (NotFound), the patch payload is invalid (422), or the API server errors/conflicts.","commonSituations":"Service accounts with get-but-not-patch RBAC on namespaces; namespace concurrently deleted; API server admission webhooks rejecting the patch; transient API server issues.","solutions":["Grant patch permission on namespaces to the caller's RBAC identity.","Re-check the namespace still exists; recreate if deleted.","Retry on transient/conflict errors (409/429/5xx).","Check admission webhooks or validating policies blocking namespace annotation updates.","Read the wrapped %v error to distinguish Forbidden vs NotFound vs server errors."],"exampleFix":"// before\nerr := ch.SetInstalledVersion(ctx, client, version)\n// after\nerr := retry.OnError(retry.DefaultRetry, apierrors.IsInternalError, func() error {\n    return ch.SetInstalledVersion(ctx, client, version)\n})","handlingStrategy":"retry","validationCode":"ssar, err := k8sClient.AuthorizationV1().SelfSubjectAccessReviews().Create(ctx, &authv1.SelfSubjectAccessReview{\n    Spec: authv1.SelfSubjectAccessReviewSpec{ResourceAttributes: &authv1.ResourceAttributes{\n        Verb: \"patch\", Resource: \"namespaces\", Name: namespace,\n    }},\n}, metav1.CreateOptions{})\n// ssar.Status.Allowed must be true before calling SetInstalledVersion","typeGuard":"func isRetryableAPIErr(err error) bool {\n    return apierrors.IsConflict(err) || apierrors.IsTooManyRequests(err) || apierrors.IsInternalError(err)\n}","tryCatchPattern":"err := retry.OnError(retry.DefaultBackoff, isRetryableAPIErr, func() error {\n    return ch.SetInstalledVersion(ctx, k8sClient, version)\n})\nif err != nil && apierrors.IsForbidden(err) {\n    return fmt.Errorf(\"RBAC: grant patch on namespaces: %w\", err)\n}","preventionTips":["Grant patch (and get) on namespaces via RBAC.","Retry transient API errors with backoff.","Check admission webhooks that may reject namespace updates.","Confirm the namespace is not being deleted (deletionTimestamp) before patching."],"tags":["kubernetes","patch","rbac","annotations"],"backgroundTag":"kubernetes-patch-failed","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"}