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

  1. Verify workers are registered: check http://<coordinator>:8080/v1/node (or UI Workers count) and restart crashed presto-server worker processes.
  2. Check worker-to-coordinator connectivity/discovery config (discovery.uri on workers, node-scheduler.include-coordinator) and fix mismatched hosts/ports.
  3. If the coordinator is the only machine, set node-scheduler.include-coordinator=true or add real workers.
  4. If HARD_AFFINITY (bucketed) splits target dead nodes, repair/restore the missing nodes or rewrite table bucketing / rescan partitions.
  5. Lower concurrent query load or raise scheduler.max-tasks-per-stage so nodes become eligible again.
  6. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/05077c85e95be91f. Report an issue: GitHub.