{"record":{"id":"e99e4fdf8cfa1607","repo":"cilium/cilium","slug":"failed-to-update-gateway-status-while-handling-the","errorCode":null,"errorMessage":"failed to update Gateway status while handling the reconcile error: %w: %w","messagePattern":"failed to update Gateway status while handling the reconcile error: %w: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"operator/pkg/gateway-api/gamma_reconcile.go","lineNumber":395,"sourceCode":"\t\tsetMergedLabelsAndAnnotations(cec, desired)\n\t\treturn nil\n\t})\n\treturn err\n}\n\nfunc (r *gammaReconciler) updateStatus(ctx context.Context, original *corev1.Service, new *corev1.Service) error {\n\toldStatus := original.Status.DeepCopy()\n\tnewStatus := new.Status.DeepCopy()\n\n\tif cmp.Equal(oldStatus, newStatus, cmpopts.IgnoreFields(metav1.Condition{}, lastTransitionTime)) {\n\t\treturn nil\n\t}\n\treturn r.client.Status().Update(ctx, new)\n}\n\nfunc (r *gammaReconciler) handleReconcileErrorWithStatus(ctx context.Context, reconcileErr error, original *corev1.Service, modified *corev1.Service) (ctrl.Result, error) {\n\tif err := r.updateStatus(ctx, original, modified); err != nil {\n\t\treturn controllerruntime.Fail(fmt.Errorf(\"failed to update Gateway status while handling the reconcile error: %w: %w\", reconcileErr, err))\n\t}\n\n\treturn controllerruntime.Fail(reconcileErr)\n}\n\nfunc (r *gammaReconciler) updateHTTPRouteStatus(ctx context.Context, original *gatewayv1.HTTPRoute, new *gatewayv1.HTTPRoute) error {\n\toldStatus := original.Status.DeepCopy()\n\tnewStatus := new.Status.DeepCopy()\n\n\tif cmp.Equal(oldStatus, newStatus, cmpopts.IgnoreFields(metav1.Condition{}, lastTransitionTime)) {\n\t\treturn nil\n\t}\n\tr.logger.DebugContext(ctx, \"Updating HTTPRoute status\", httpRoute, types.NamespacedName{Name: original.Name, Namespace: original.Namespace})\n\treturn r.client.Status().Update(ctx, new)\n}\n\nfunc (r *gammaReconciler) handleHTTPRouteReconcileErrorWithStatus(ctx context.Context, reconcileErr error, original *gatewayv1.HTTPRoute, modified *gatewayv1.HTTPRoute) error {\n\tif err := r.updateHTTPRouteStatus(ctx, original, modified); err != nil {","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/operator/pkg/gateway-api/gamma_reconcile.go#L377-L413","documentation":"This error is thrown by gammaReconciler.handleReconcileErrorWithStatus when the operator fails to update the Gateway Service's status subresource while already handling an original reconcile error. It wraps BOTH errors: the original reconcileErr and the status-update err, using Go's multi-%w wrapping so both can be unwrapped with errors.Is/As. The library throws it so the operator log shows the root cause AND the secondary failure that occurred during error handling.","triggerScenarios":"Reconcile() hits an error reconciling the Gateway's provisioned Service (reconcileErr), then the follow-up updateStatus call — r.client.Status().Update(ctx, modified) on the corev1.Service — also fails (e.g. due to conflict, RBAC denial on Service/status, or the Service being deleted mid-reconcile).","commonSituations":"Concurrent controllers updating the same Service status causing 409 Conflict (optimistic concurrency failure, stale resourceVersion); Service deleted by another actor while reconciliation fails; operator service account lacking update permission on services/status; API server transient unavailability.","solutions":["Check the second wrapped error (%w after the colon) first — it is usually a 409 Conflict; re-trigger reconciliation (retry backoff) so the next attempt reads a fresh resourceVersion and updates status successfully.","Verify the operator's RBAC allows updating the status subresource: clusterrole must include 'services/status' update (and gateway API resources if applicable).","Confirm the managed Service was not deleted out-of-band (GitOps flux/argocd pruning, kubectl delete); restore owner references or re-run reconcile.","Inspect the first wrapped error to fix the original reconcile failure (e.g. missing GatewayClass, invalid config) — fixing only the status error hides the real problem."],"exampleFix":"// before: rbac allowing only core Services\n- apiGroups: [\"\"]\n  resources: [\"services\"]\n  verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\"]\n// after: include the status subresource\n- apiGroups: [\"\"]\n  resources: [\"services\", \"services/status\"]\n  verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\"]","handlingStrategy":"retry","validationCode":"// before reconcile: verify RBAC and Service existence\nsvc := &corev1.Service{}\nif err := k8sClient.Get(ctx, types.NamespacedName{Name: gwName, Namespace: gwNs}, svc); err != nil {\n    return fmt.Errorf(\"gateway Service %s/%s not retrievable: %w\", gwNs, gwName, err)\n}\n// ensure SubjectAccessReview allows services/status update","typeGuard":"// unwrap and classify the double-wrapped error\ntype statusUpdateErr struct{ ReconcileErr, UpdateErr error }\nfunc IsStatusUpdateConflict(err error) bool {\n    return apierrors.IsConflict(err) || apierrors.IsConflict(errors.Unwrap(errors.Unwrap(err)))\n}","tryCatchPattern":"res, err := reconciler.Reconcile(ctx, req)\nif err != nil {\n    if apierrors.IsConflict(err) || strings.Contains(err.Error(), \"failed to update Gateway status\") {\n        // transient: rely on controller-runtime backoff\n        return // requeue happens automatically\n    }\n    log.Error(err, \"persistent reconcile failure\")\n}","preventionTips":["Include services/status in the operator RBAC before deploying.","Avoid multiple controllers writing the same Service status concurrently.","Let controller-runtime exponential backoff handle Conflict errors instead of manual immediate retries.","Monitor 409 Conflict rates on status subresources to detect fighting controllers."],"tags":["kubernetes","operator","status-update","error-wrapping"],"backgroundTag":"kubernetes-status-update-conflict","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}