{"record":{"id":"cda3043d9f6443bb","repo":"GoogleContainerTools/skaffold","slug":"s-0-d-nodes-available-s","errorCode":null,"errorMessage":"%s: 0/%d nodes available: %s","messagePattern":"(.+?): 0/(.+?) nodes available: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/diag/validator/validator.go","lineNumber":274,"sourceCode":"\t\t\t}\n\t\tcase v1.TaintNodeUnreachable:\n\t\t\tmessages[i] = \"1 node is unreachable\"\n\t\t\tif errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {\n\t\t\t\terrCode = proto.StatusCode_STATUSCHECK_NODE_UNREACHABLE\n\t\t\t}\n\t\tcase v1.TaintNodeUnschedulable:\n\t\t\tmessages[i] = \"1 node is unschedulable\"\n\t\t\tif errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {\n\t\t\t\terrCode = proto.StatusCode_STATUSCHECK_NODE_UNSCHEDULABLE\n\t\t\t}\n\t\tcase v1.TaintNodeNetworkUnavailable:\n\t\t\tmessages[i] = \"1 node's network not available\"\n\t\t\tif errCode == proto.StatusCode_STATUSCHECK_UNKNOWN_UNSCHEDULABLE {\n\t\t\t\terrCode = proto.StatusCode_STATUSCHECK_NODE_NETWORK_UNAVAILABLE\n\t\t\t}\n\t\t}\n\t}\n\treturn errCode, fmt.Errorf(\"%s: 0/%d nodes available: %s\", reason, len(messages), strings.Join(messages, \", \"))\n}\n\nfunc processPodEvents(e corev1.EventInterface, pod v1.Pod, ps *podStatus) *podStatus {\n\tupdated := ps\n\tif _, ok := unknownConditionsOrSuccess[ps.ae.ErrCode]; !ok {\n\t\treturn updated\n\t}\n\tlog.Entry(context.TODO()).Debugf(\"Fetching events for pod %q\", pod.Name)\n\t// Get pod events.\n\tscheme := runtime.NewScheme()\n\tscheme.AddKnownTypes(v1.SchemeGroupVersion, &pod)\n\tevents, err := e.Search(scheme, &pod)\n\tif err != nil {\n\t\tlog.Entry(context.TODO()).Debugf(\"Could not fetch events for resource %q due to %v\", pod.Name, err)\n\t\treturn updated\n\t}\n\t// find the latest event.\n\tvar recentEvent *v1.Event","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/diag/validator/validator.go#L256-L292","documentation":"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.","triggerScenarios":"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, \", \")).","commonSituations":"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.","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."],"exampleFix":"// before: pod lacks toleration for unreachable node taint\n// after\n// tolerations:\n// - key: node.kubernetes.io/network-unavailable\n//   operator: Exists\n//   effect: NoSchedule","handlingStrategy":"validation","validationCode":"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)) } } }","typeGuard":"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 }","tryCatchPattern":"code, err := getUntoleratedTaints(reason, msg); if errors.Is(err, errUnschedulable) { for _, part := range strings.Split(msg, \": \") { log.Println(\"node reason:\", part) } }","preventionTips":["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"],"tags":["kubernetes","scheduling","taints","nodes"],"backgroundTag":"pod-unschedulable-taints","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}