GoogleContainerTools/skaffold · error
%s: 0/%d nodes available: %s
Error message
%s: 0/%d nodes available: %s
What it means
Aggregated scheduling-failure error listing why each candidate node was rejected: '0/N nodes available'. It carries code STATUSCHECK_UNKNOWN_UNSCHEDULABLE or a more specific taint-derived code (e.g. node network unavailable). Skaffold derives one message per matched taint/reason from the scheduler event.
Source
Thrown at pkg/diag/validator/validator.go:274
}
case v1.TaintNodeUnreachable:
messages[i] = "1 node is unreachable"
if errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {
errCode = proto.StatusCode_STATUSCHECK_NODE_UNREACHABLE
}
case v1.TaintNodeUnschedulable:
messages[i] = "1 node is unschedulable"
if errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {
errCode = proto.StatusCode_STATUSCHECK_NODE_UNSCHEDULABLE
}
case v1.TaintNodeNetworkUnavailable:
messages[i] = "1 node's network not available"
if errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {
errCode = proto.StatusCode_STATUSCHECK_NODE_NETWORK_UNAVAILABLE
}
}
}
return errCode, fmt.Errorf("%s: 0/%d nodes available: %s", reason, len(messages), strings.Join(messages, ", "))
}
func processPodEvents(e corev1.EventInterface, pod v1.Pod, ps *podStatus) *podStatus {
updated := ps
if _, ok := unknownConditionsOrSuccess[ps.ae.ErrCode]; !ok {
return updated
}
log.Entry(context.TODO()).Debugf("Fetching events for pod %q", pod.Name)
// Get pod events.
scheme := runtime.NewScheme()
scheme.AddKnownTypes(v1.SchemeGroupVersion, &pod)
events, err := e.Search(scheme, &pod)
if err != nil {
log.Entry(context.TODO()).Debugf("Could not fetch events for resource %q due to %v", pod.Name, err)
return updated
}
// find the latest event.
var recentEvent *v1.EventView on GitHub (pinned to a1189de023)
Solutions
- Read the per-node reasons in the message; for each, either fix the node condition or add a matching toleration to the pod.
- Uncordon unhealthy nodes: kubectl uncordon <node>, and fix node NotReady/network conditions.
- Add tolerations for legitimate persistent taints, e.g. tolerations for node.kubernetes.io/not-ready as appropriate.
- Scale the cluster (add nodes) if all nodes are genuinely full or tainted.
Example fix
// before: pod lacks toleration for unreachable node taint // after // tolerations: // - key: node.kubernetes.io/network-unavailable // operator: Exists // effect: NoSchedule
Defensive patterns
Strategy: validation
Validate before calling
for _, n := range nodes.Items { for _, t := range n.Spec.Taints { if !tolerated(pod.Spec.Tolerations, t) { issues = append(issues, fmt.Sprintf("node %s tainted %s=%s", n.Name, t.Key, t.Effect)) } } } Type guard
func allTaintsTolerated(nodes []v1.Node, tolerations []v1.Toleration) bool { for _, n := range nodes { for _, t := range n.Spec.Taints { if !tolerates(tolerations, t) { return false } } } return len(nodes) > 0 } Try / catch
code, err := getUntoleratedTaints(reason, msg); if errors.Is(err, errUnschedulable) { for _, part := range strings.Split(msg, ": ") { log.Println("node reason:", part) } } Prevention
- Run cluster-autoscaler or keep headroom so nodes aren't fully tainted/full
- Uncordon nodes after maintenance (kubectl uncordon)
- Add standard tolerations for unavoidable infra taints only where safe
- Alert on node NotReady/network-unavailable conditions
When it happens
Trigger: getUntoleratedTaints matches taintsRe in the scheduler's failure message, builds a `messages` array from the matched taints/reasons, and returns fmt.Errorf("%s: 0/%d nodes available: %s", reason, len(messages), strings.Join(messages, ", ")).
Common situations: All nodes tainted (e.g. node.kubernetes.io/unreachable, not-ready, network unavailable) and the pod lacks tolerations; single-node clusters (minikube/kind) with the node tainted; cluster autoscaler not running while nodes are cordoned.
Related errors
- STATUSCHECK_UNKNOWN_UNSCHEDULABLE
- c.Message (pod status condition message)
- unable to lookup minikube executable. Please add it to PATH
- invalid local-registry-hosting ConfigMap
- strings.Join(errMsgs, "\n") (joined helm cleanup error messa
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/cda3043d9f6443bb.
Report an issue: GitHub.