prestodb/presto · error · PrestoException
NO_NODES_AVAILABLE
NO_NODES_AVAILABLE
Error message
No nodes available to run query
What it means
SimpleNodeSelector.computeAssignments throws NO_NODES_AVAILABLE when the candidate node list computed for a split is empty, meaning the scheduler cannot place splits because no active worker nodes are eligible. Presto throws this to fail the query fast instead of leaving it stuck in an unschedulable state. Candidates are derived from active nodes in the NodeMap (filtered by include-coordinator, max tasks per stage, and affinity preferences), so an empty result means workers are missing, shutting down, or excluded.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/scheduler/nodeSelection/SimpleNodeSelector.java:192
break;
case SOFT_AFFINITY:
candidateNodes = selectExactNodes(nodeMap, split.getPreferredNodes(nodeProvider), includeCoordinator);
preferredNodeCount = OptionalInt.of(candidateNodes.size());
candidateNodes = ImmutableList.<InternalNode>builder()
.addAll(candidateNodes)
.addAll(randomNodeSelection.pickNodes(split))
.build();
break;
case NO_PREFERENCE:
candidateNodes = randomNodeSelection.pickNodes(split);
break;
default:
throw new PrestoException(NODE_SELECTION_NOT_SUPPORTED, format("Unsupported node selection strategy %s", split.getNodeSelectionStrategy()));
}
if (candidateNodes.isEmpty()) {
log.debug("No nodes available to schedule %s. Available nodes %s", split, nodeMap.getActiveNodes());
throw new PrestoException(NO_NODES_AVAILABLE, "No nodes available to run query");
}
SplitWeight splitWeight = split.getSplitWeight();
Optional<InternalNodeInfo> chosenNodeInfo = Optional.empty();
if (taskLoadSplitWeightProvider.isPresent()) {
chosenNodeInfo = chooseLeastBusyNode(splitWeight, candidateNodes, taskLoadSplitWeightProvider.get(), preferredNodeCount, maxSplitsWeightPerTask, assignmentStats);
}
else {
chosenNodeInfo = chooseLeastBusyNode(splitWeight, candidateNodes, assignmentStats::getTotalSplitsWeight, preferredNodeCount, maxSplitsWeightPerNode, assignmentStats);
if (!chosenNodeInfo.isPresent()) {
chosenNodeInfo = chooseLeastBusyNode(splitWeight, candidateNodes, assignmentStats::getQueuedSplitsWeightForStage, preferredNodeCount, maxPendingSplitsWeightPerTask, assignmentStats);
}
}
if (chosenNodeInfo.isPresent()) {
split = new Split(
split.getConnectorId(),View on GitHub (pinned to 55bb57d202)
Solutions
- Verify workers are registered: check http://<coordinator>:8080/v1/node (or UI Workers count) and restart crashed presto-server worker processes.
- Check worker-to-coordinator connectivity/discovery config (discovery.uri on workers, node-scheduler.include-coordinator) and fix mismatched hosts/ports.
- If the coordinator is the only machine, set node-scheduler.include-coordinator=true or add real workers.
- If HARD_AFFINITY (bucketed) splits target dead nodes, repair/restore the missing nodes or rewrite table bucketing / rescan partitions.
- Lower concurrent query load or raise scheduler.max-tasks-per-stage so nodes become eligible again.
- Check coordinator logs for the debug line 'No nodes available to schedule' to see which split and which nodes were active.
Example fix
// before (etc/config.properties on coordinator) node-scheduler.include-coordinator=false // cluster has only the coordinator node -> NO_NODES_AVAILABLE // after node-scheduler.include-coordinator=true // or start presto workers pointing at the same discovery.uri
Defensive patterns
Strategy: try-catch
Validate before calling
// Before submitting, verify worker availability
List<InternalNode> nodes = nodeSelector.getActiveNodes();
if (nodes.isEmpty() || (nodes.size() == 1 && nodes.get(0).isCoordinator() && !includeCoordinator)) {
throw new IllegalStateException("No active worker nodes available to schedule query");
} Type guard
private static boolean hasSchedulableNodes(List<InternalNode> activeNodes, boolean includeCoordinator) {
return activeNodes.stream().anyMatch(n -> includeCoordinator || !n.isCoordinator());
} Try / catch
try {
SplitPlacementResult result = nodeSelector.computeAssignments(splits, existingTasks);
} catch (PrestoException e) {
if (e.getErrorCode() == StandardErrorCode.NO_NODES_AVAILABLE.toErrorCode().getCode()) {
// check /v1/node, restart workers or wait for cluster to recover, then resubmit
throw new QuerySchedulingException("Cluster has no eligible worker nodes", e);
}
throw e;
} Prevention
- Monitor worker registration via the coordinator's /v1/node endpoint and alert when active workers drop below a threshold.
- Keep node-scheduler.include-coordinator set appropriately for single-node/dev clusters.
- Avoid decommissioning workers while queries are running; drain gracefully.
- Set max-tasks-per-stage and concurrency limits so eligible-node filtering never empties the pool.
- Check coordinator debug logs for 'No nodes available to schedule' to catch affinity targeting dead nodes early.
When it happens
Trigger: A query is submitted while zero worker nodes are active/registered (all workers crashed, coordinator started without workers, or include-coordinator=false with only the coordinator present); HARD_AFFINITY splits whose preferred nodes are all absent; or getEligibleNodes(maxTasksPerStage) returns empty because existing tasks already saturate maxTasksPerStage.
Common situations: Workers failed to register (misconfigured discovery URI, wrong node-scheduler.include-coordinator setting); workers killed by autoscaling or OOM during a query; query submitted right after cluster startup before workers join; Hive/HDFS datanode-preferred splits pointing at decommissioned nodes; too much concurrency hitting max-tasks-per-stage so no node is eligible.
Related errors
- NO_NODES_AVAILABLE
- NO_NODES_AVAILABLE
- NODE_SELECTION_NOT_SUPPORTED
- NO_NODES_AVAILABLE
- INVALID_TABLE_PROPERTY
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/05077c85e95be91f.
Report an issue: GitHub.