prestodb/presto · error · IllegalArgumentException
non-native (java) execution requires only one scheduledSplit
Error message
non-native (java) execution requires only one scheduledSplits but [%d] were found [%s]
What it means
In Java (non-native) execution, each Spark task's driver is created with exactly one scheduled split; PrestoSparkTaskExecution.createDriver enforces this and throws IllegalArgumentException when more than one split is supplied. This is an internal invariant: the Java driver assumes a single split per task.
Source
Thrown at presto-spark-base/src/main/java/com/facebook/presto/spark/execution/task/PrestoSparkTaskExecution.java:368
this.pipelineContext = taskContext.addPipelineContext(driverFactory.getPipelineId(), driverFactory.isInputDriver(), driverFactory.isOutputDriver(), partitioned);
}
public DriverSplitRunner createDriverRunner(@Nullable List<ScheduledSplit> scheduledSplits)
{
checkState(!noMoreDriverRunner.get(), "Cannot create driver for pipeline: %s", pipelineContext.getPipelineId());
pendingCreation.incrementAndGet();
// create driver context immediately so the driver existence is recorded in the stats
// splitWeight can be 0 as we don't load balance the executor based on their load average
DriverContext driverContext = pipelineContext.addDriverContext(0, Lifespan.taskWide(), driverFactory.getFragmentResultCacheContext());
return new DriverSplitRunner(this, driverContext, scheduledSplits);
}
public Driver createDriver(DriverContext driverContext, @Nullable List<ScheduledSplit> scheduledSplits)
{
Driver driver = driverFactory.createDriver(driverContext);
if (scheduledSplits != null && scheduledSplits.size() > 0) {
if (!nativeExecution && scheduledSplits.size() != 1) {
throw new IllegalArgumentException(format("non-native (java) execution requires only one scheduledSplits but [%d] were found [%s]",
scheduledSplits.size(),
Joiner.on(",").join(scheduledSplits.stream().map(ScheduledSplit::toString).collect(Collectors.toList()))));
}
PlanNodeId sourceNodeId = nativeExecution ? driver.getSourceId().get() : Iterables.getOnlyElement(scheduledSplits).getPlanNodeId();
// TableScanOperator requires partitioned split to be added before the first call to process
driver.updateSource(new TaskSource(sourceNodeId, ImmutableSet.copyOf(scheduledSplits), true));
}
verify(pendingCreation.get() > 0, "pendingCreation is expected to be greater than zero");
pendingCreation.decrementAndGet();
closeDriverFactoryIfFullyCreated();
return driver;
}
public void noMoreDriverRunner()
{View on GitHub (pinned to 55bb57d202)
Solutions
- Verify each Java-execution task input maps exactly one scheduled split per driver; inspect PrestoSparkTaskInputs construction
- Ensure you are not accidentally routing native-style multi-split inputs to the Java executor (check nativeExecution flag consistency)
- Upgrade Presto on Spark version — internal split assignment logic may have been fixed
- If you supply custom task inputs, fix your partitioning logic to emit one split per task
Example fix
// before (custom input builder) taskInputs.add(split1); taskInputs.add(split2); // after checkState(splits.size() == 1, "java execution supports exactly one split per task"); taskInputs.add(Iterables.getOnlyElement(splits));
Defensive patterns
Strategy: validation
Validate before calling
if (!nativeExecution && scheduledSplits != null && scheduledSplits.size() > 1) {
throw new IllegalArgumentException("java execution requires exactly one split, got " + scheduledSplits.size());
} Type guard
boolean hasSingleSplit(List<ScheduledSplit> splits) { return splits == null || splits.size() <= 1; } Try / catch
try { driver = createDriver(ctx, splits); } catch (IllegalArgumentException e) { if (e.getMessage().contains("only one scheduledSplits")) { log.error("multi-split input for java driver", e); } throw e; } Prevention
- Never hand-craft PrestoSparkTaskInputs with multiple splits per task for java execution
- Keep the nativeExecution flag consistent across coordinator and executor
- Test custom input partitioning against the one-split invariant in unit tests
When it happens
Trigger: createDriver is invoked with a scheduledSplits list of size > 1 while nativeExecution is false (a Spark task receives multiple scheduled splits in PrestoSparkTaskInputs for a non-native execution).
Common situations: Bugs or custom modifications in PrestoSparkInput partitioning logic that assign multiple splits to a single task; corrupted or hand-crafted RDD inputs; version mismatches between coordinator task planning and Spark executor inputs.
Related errors
- Unexpected fragment partitioning %s, fragmentId: %s
- Invalid day-time interval:
- Invalid year-month interval:
- dictionarySourceIds must be the same
- blocks is empty
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/3d7b50563160dcff.
Report an issue: GitHub.