{"record":{"id":"747bb0c7740f6348","repo":"cilium/cilium","slug":"unmarkpool-w","errorCode":null,"errorMessage":"unmarkPool: %w","messagePattern":"unmarkPool: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"operator/pkg/lbipam/lbipam.go","lineNumber":1789,"sourceCode":"\t\t}\n\n\t\tpoolConflict := false\n\t\tfor _, poolInner := range ipam.pools {\n\t\t\tif poolOuter.GetName() == poolInner.GetName() {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif conflicting, _, _ := areRangesConflicting(poolOuter.ranges, poolInner.ranges); conflicting {\n\t\t\t\tpoolConflict = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// The outer pool, which is marked conflicting no longer conflicts\n\t\tif !poolConflict {\n\t\t\terr := ipam.unmarkPool(ctx, poolOuter)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"unmarkPool: %w\", err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Count the number of conflicting pools and update the metric.\n\tvar conflictingPools float64\n\tfor _, pool := range ipam.pools {\n\t\t// When a pool is marked as conflicting, all of its lbRanges are\n\t\t// internally disabled. Therefore, checking a single lbRange\n\t\t// is sufficient to conclude that the pool is conflicting.\n\t\tif len(pool.ranges) > 0 && pool.ranges[0].internallyDisabled {\n\t\t\tconflictingPools++\n\t\t}\n\t}\n\n\tipam.metrics.ConflictingPools.Set(conflictingPools)\n\n\treturn nil","sourceCodeStart":1771,"sourceCodeEnd":1807,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/operator/pkg/lbipam/lbipam.go#L1771-L1807","documentation":"Thrown when unmarkPool fails. During conflict reconciliation, if a pool that was previously marked conflicting no longer conflicts, LB-IPAM calls unmarkPool to clear the CiliumPoolConflict condition (set to False with reason 'resolved'); the resulting status patch failure is wrapped as 'unmarkPool: %w'.","triggerScenarios":"Reconciliation finds poolOuter marked conflicting but its ranges no longer overlap; the patch clearing the conflict condition on the pool status fails (API error, RBAC, resourceVersion conflict).","commonSituations":"An admin deleted/edited the overlapping pool so conflict resolved, but the API server is degraded or the operator lacks status patch permissions, so the stale 'conflicting' condition cannot be cleared.","solutions":["Inspect the wrapped error for the patch failure reason.","Ensure the operator can patch ciliumloadbalancerippools/status.","Check API server health and retry; the reconcile loop will re-run unmarkPool.","As a workaround, manually remove the stale condition with kubectl patch on the pool status."],"exampleFix":"// manual workaround\nkubectl patch ciliumloadbalancerippool <name> --subresource status --type json \\\n  -p '[{\"op\":\"remove\",\"path\":\"/status/conditions/0\"}]'","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := ipam.unmarkPool(ctx, poolOuter); err != nil {\n    return fmt.Errorf(\"unmarkPool: %w\", err) // retried on next reconcile\n}","preventionTips":["Confirm operator can patch pool status before relying on automatic unmark.","Clear stale conflict conditions manually if the operator is stuck: kubectl patch ... --subresource status.","Monitor pool conditions for entries stuck in conflicting after ranges were fixed."],"tags":["kubernetes","ipam","status-patch"],"backgroundTag":"k8s-status-patch-failed","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}