{"record":{"id":"3d7b50563160dcff","repo":"prestodb/presto","slug":"non-native-java-execution-requires-only-one-sche","errorCode":null,"errorMessage":"non-native (java) execution requires only one scheduledSplits but [%d] were found [%s]","messagePattern":"non-native \\(java\\) execution requires only one scheduledSplits but \\[(.+?)\\] were found \\[(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-spark-base/src/main/java/com/facebook/presto/spark/execution/task/PrestoSparkTaskExecution.java","lineNumber":368,"sourceCode":"            this.pipelineContext = taskContext.addPipelineContext(driverFactory.getPipelineId(), driverFactory.isInputDriver(), driverFactory.isOutputDriver(), partitioned);\n        }\n\n        public DriverSplitRunner createDriverRunner(@Nullable List<ScheduledSplit> scheduledSplits)\n        {\n            checkState(!noMoreDriverRunner.get(), \"Cannot create driver for pipeline: %s\", pipelineContext.getPipelineId());\n            pendingCreation.incrementAndGet();\n            // create driver context immediately so the driver existence is recorded in the stats\n            // splitWeight can be 0 as we don't load balance the executor based on their load average\n            DriverContext driverContext = pipelineContext.addDriverContext(0, Lifespan.taskWide(), driverFactory.getFragmentResultCacheContext());\n            return new DriverSplitRunner(this, driverContext, scheduledSplits);\n        }\n\n        public Driver createDriver(DriverContext driverContext, @Nullable List<ScheduledSplit> scheduledSplits)\n        {\n            Driver driver = driverFactory.createDriver(driverContext);\n            if (scheduledSplits != null && scheduledSplits.size() > 0) {\n                if (!nativeExecution && scheduledSplits.size() != 1) {\n                    throw new IllegalArgumentException(format(\"non-native (java) execution requires only one scheduledSplits but [%d] were found [%s]\",\n                            scheduledSplits.size(),\n                            Joiner.on(\",\").join(scheduledSplits.stream().map(ScheduledSplit::toString).collect(Collectors.toList()))));\n                }\n                PlanNodeId sourceNodeId = nativeExecution ? driver.getSourceId().get() : Iterables.getOnlyElement(scheduledSplits).getPlanNodeId();\n                // TableScanOperator requires partitioned split to be added before the first call to process\n                driver.updateSource(new TaskSource(sourceNodeId, ImmutableSet.copyOf(scheduledSplits), true));\n            }\n\n            verify(pendingCreation.get() > 0, \"pendingCreation is expected to be greater than zero\");\n            pendingCreation.decrementAndGet();\n\n            closeDriverFactoryIfFullyCreated();\n\n            return driver;\n        }\n\n        public void noMoreDriverRunner()\n        {","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spark-base/src/main/java/com/facebook/presto/spark/execution/task/PrestoSparkTaskExecution.java#L350-L386","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before (custom input builder)\ntaskInputs.add(split1);\ntaskInputs.add(split2);\n// after\ncheckState(splits.size() == 1, \"java execution supports exactly one split per task\");\ntaskInputs.add(Iterables.getOnlyElement(splits));","handlingStrategy":"validation","validationCode":"if (!nativeExecution && scheduledSplits != null && scheduledSplits.size() > 1) {\n    throw new IllegalArgumentException(\"java execution requires exactly one split, got \" + scheduledSplits.size());\n}","typeGuard":"boolean hasSingleSplit(List<ScheduledSplit> splits) { return splits == null || splits.size() <= 1; }","tryCatchPattern":"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; }","preventionTips":["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"],"tags":["presto-on-spark","illegal-argument","scheduled-splits","java-execution"],"backgroundTag":"multiple-splits-per-driver","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}