{"record":{"id":"d5a2743eb02c9d17","repo":"derailed/k9s","slug":"node-is-cordoned","errorCode":null,"errorMessage":"node is cordoned","messagePattern":"node is cordoned","errorType":"exception","errorClass":"cordonErr","httpStatus":null,"severity":"warning","filePath":"internal/render/node.go","lineNumber":35,"sourceCode":"\t\"github.com/derailed/k9s/internal/model1\"\n\t\"github.com/derailed/k9s/internal/slogs\"\n\t\"github.com/derailed/tcell/v2\"\n\t\"github.com/derailed/tview\"\n\tv1 \"k8s.io/api/core/v1\"\n\t\"k8s.io/apimachinery/pkg/api/resource\"\n\t\"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/apimachinery/pkg/runtime/schema\"\n\tmv1beta1 \"k8s.io/metrics/pkg/apis/metrics/v1beta1\"\n)\n\nconst (\n\tlabelNodeRolePrefix = \"node-role.kubernetes.io/\"\n\tlabelNodeRoleSuffix = \"kubernetes.io/role\"\n)\n\nvar (\n\tcordonErr   = errors.New(\"node is cordoned\")\n\tnotReadyErr = errors.New(\"node is not ready\")\n)\n\nvar defaultNOHeader = model1.Header{\n\tmodel1.HeaderColumn{Name: \"NAME\"},\n\tmodel1.HeaderColumn{Name: \"STATUS\"},\n\tmodel1.HeaderColumn{Name: \"ROLE\"},\n\tmodel1.HeaderColumn{Name: \"ARCH\", Attrs: model1.Attrs{Wide: true}},\n\tmodel1.HeaderColumn{Name: \"TAINTS\"},\n\tmodel1.HeaderColumn{Name: \"VERSION\"},\n\tmodel1.HeaderColumn{Name: \"OS-IMAGE\", Attrs: model1.Attrs{Wide: true}},\n\tmodel1.HeaderColumn{Name: \"KERNEL\", Attrs: model1.Attrs{Wide: true}},\n\tmodel1.HeaderColumn{Name: \"INTERNAL-IP\", Attrs: model1.Attrs{Wide: true}},\n\tmodel1.HeaderColumn{Name: \"EXTERNAL-IP\", Attrs: model1.Attrs{Wide: true}},\n\tmodel1.HeaderColumn{Name: \"PODS\", Attrs: model1.Attrs{Align: tview.AlignRight}},\n\tmodel1.HeaderColumn{Name: \"CPU\", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},\n\tmodel1.HeaderColumn{Name: \"CPU/A\", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},\n\tmodel1.HeaderColumn{Name: \"%CPU\", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/render/node.go#L17-L53","documentation":"Sentinel error `cordonErr` in the k9s node renderer. `Node.diagnose` (internal/render/node.go:186) builds the status token list via `status(conds, node.Spec.Unschedulable, ...)`, which appends \"SchedulingDisabled\" when `spec.unschedulable` is true (node was cordoned via `kubectl cordon`). If the node is Ready but cordoned, diagnose returns this error; it is rendered into the VALID column and the row is colored with PendingColor, and it also flows into the view's health check. It is a status signal, not a program failure.","triggerScenarios":"Calling Node.Render/Node.Healthy on a node whose `spec.unschedulable` is true and whose Ready condition is True: the STATUS column contains \"SchedulingDisabled\" and diagnose() takes the `cordoned` branch (internal/render/node.go:210).","commonSituations":"Operator ran `kubectl cordon` before maintenance or node drain; cluster autoscaler marked the node unschedulable; k9s node view shows VALID=\"node is cordoned\" on a yellow row and the flash/health indicator reports it.","solutions":["Confirm the cordon is intentional (maintenance, drain in progress); the node still runs existing pods, it only stops accepting new ones","Uncordon it: `kubectl uncordon <node-name>`, then refresh the node view","If scheduling must stay disabled, treat the message as informational — it does not mean the node is broken","Check why the node was cordoned: `kubectl describe node <name>` and look at taints/events if you did not cordon it yourself"],"exampleFix":"# before\nkubectl cordon worker-1   # node shows: node is cordoned\n# after\nkubectl uncordon worker-1  # VALID column clears after refresh","handlingStrategy":"validation","validationCode":"// Before acting on node health, check the cordon flag directly:\nunschedulable, _ := unstructured.NestedBool(node.Object, \"spec\", \"unschedulable\")\nif unschedulable {\n    // treat as cordoned: informational, not a failure\n}","typeGuard":"func isCordoned(n *v1.Node) bool {\n    return n != nil && n.Spec.Unschedulable\n}","tryCatchPattern":"if err := nodeRenderer.Healthy(ctx, obj); err != nil {\n    if errors.Is(err, render.CordonErr) { /* log/ignore: node is cordoned */ }\n    // handle other errors\n}","preventionTips":["Check spec.unschedulable before treating node status as an error","Reserve drain/cordon windows so dashboards are not surprised","Uncordon nodes promptly after maintenance"],"tags":["kubernetes","node","cordon","render","k9s"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}