derailed/k9s · warning · cordonErr
node is cordoned
Error message
node is cordoned
What it means
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.
Source
Thrown at internal/render/node.go:35
"github.com/derailed/k9s/internal/model1"
"github.com/derailed/k9s/internal/slogs"
"github.com/derailed/tcell/v2"
"github.com/derailed/tview"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
)
const (
labelNodeRolePrefix = "node-role.kubernetes.io/"
labelNodeRoleSuffix = "kubernetes.io/role"
)
var (
cordonErr = errors.New("node is cordoned")
notReadyErr = errors.New("node is not ready")
)
var defaultNOHeader = model1.Header{
model1.HeaderColumn{Name: "NAME"},
model1.HeaderColumn{Name: "STATUS"},
model1.HeaderColumn{Name: "ROLE"},
model1.HeaderColumn{Name: "ARCH", Attrs: model1.Attrs{Wide: true}},
model1.HeaderColumn{Name: "TAINTS"},
model1.HeaderColumn{Name: "VERSION"},
model1.HeaderColumn{Name: "OS-IMAGE", Attrs: model1.Attrs{Wide: true}},
model1.HeaderColumn{Name: "KERNEL", Attrs: model1.Attrs{Wide: true}},
model1.HeaderColumn{Name: "INTERNAL-IP", Attrs: model1.Attrs{Wide: true}},
model1.HeaderColumn{Name: "EXTERNAL-IP", Attrs: model1.Attrs{Wide: true}},
model1.HeaderColumn{Name: "PODS", Attrs: model1.Attrs{Align: tview.AlignRight}},
model1.HeaderColumn{Name: "CPU", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},
model1.HeaderColumn{Name: "CPU/A", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},
model1.HeaderColumn{Name: "%CPU", Attrs: model1.Attrs{Align: tview.AlignRight, MX: true}},View on GitHub (pinned to 2d3ccc6ba2)
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
Example fix
# before kubectl cordon worker-1 # node shows: node is cordoned # after kubectl uncordon worker-1 # VALID column clears after refresh
Defensive patterns
Strategy: validation
Validate before calling
// Before acting on node health, check the cordon flag directly:
unschedulable, _ := unstructured.NestedBool(node.Object, "spec", "unschedulable")
if unschedulable {
// treat as cordoned: informational, not a failure
} Type guard
func isCordoned(n *v1.Node) bool {
return n != nil && n.Spec.Unschedulable
} Try / catch
if err := nodeRenderer.Healthy(ctx, obj); err != nil {
if errors.Is(err, render.CordonErr) { /* log/ignore: node is cordoned */ }
// handle other errors
} Prevention
- Check spec.unschedulable before treating node status as an error
- Reserve drain/cordon windows so dashboards are not surprised
- Uncordon nodes promptly after maintenance
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- namespace not ready
- node is already cordoned
- unable to launch shell pod on node %s
- expecting a maintainer for %q
- failed benchmark
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/d5a2743eb02c9d17.
Report an issue: GitHub.