{"record":{"id":"10fcf40acab666f5","repo":"apache/iceberg","slug":"failed-while-running-parallel-task","errorCode":null,"errorMessage":"Failed while running parallel task","messagePattern":"Failed while running parallel task","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/util/ParallelIterable.java","lineNumber":164,"sourceCode":"     */\n    private synchronized boolean checkTasks() {\n      Preconditions.checkState(!closed.get(), \"Already closed\");\n      boolean hasRunningTask = false;\n\n      for (int i = 0; i < taskFutures.length; i += 1) {\n        if (taskFutures[i] == null || taskFutures[i].isDone()) {\n          if (taskFutures[i] != null) {\n            // check for task failure and re-throw any exception. Enqueue continuation if any.\n            try {\n              Optional<Task<T>> continuation = taskFutures[i].get();\n              continuation.ifPresent(yieldedTasks::addLast);\n              taskFutures[i] = null;\n            } catch (ExecutionException e) {\n              if (e.getCause() instanceof RuntimeException) {\n                // rethrow a runtime exception\n                throw (RuntimeException) e.getCause();\n              } else {\n                throw new RuntimeException(\"Failed while running parallel task\", e.getCause());\n              }\n            } catch (InterruptedException e) {\n              throw new RuntimeException(\"Interrupted while running parallel task\", e);\n            }\n          }\n\n          // submit a new task if there is space in the queue\n          if (queue.size() < maxQueueSize) {\n            taskFutures[i] = submitNextTask();\n          }\n        }\n\n        if (taskFutures[i] != null) {\n          hasRunningTask = true;\n        }\n      }\n\n      return !closed.get() && (tasks.hasNext() || hasRunningTask);","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/util/ParallelIterable.java#L146-L182","documentation":"ParallelIterable wraps a checked (non-RuntimeException) Throwable thrown by one of its worker tasks in a RuntimeException with this message. Because ExecutionException loses the direct throw, the original cause is attached as the cause.","triggerScenarios":"Iterating a ParallelIterable (hasNext → checkTasks) while a taskFuture completes exceptionally with a checked Throwable, e.g. an IOException thrown inside a supplied Iterable's task.","commonSituations":"Parallel manifest/file scans where one worker hits an IO error or a checked library exception.","solutions":["Inspect e.getCause() for the real failure and fix it","Wrap checked exceptions in your task iterables into RuntimeExceptions if you want them rethrown directly","Increase task robustness (retries, validation) for parallel tasks"],"exampleFix":"// before\nCloseableIterable<T> it = ParallelIterable.of(iterables, pool); // task throws IOException\n// after\nIterable<T> safe = () -> new Iterator<T>() { /* wrap IOException in RuntimeException */ };","handlingStrategy":"try-catch","validationCode":"// validate task iterables don't throw checked exceptions\niterables.forEach(it -> Preconditions.checkNotNull(it, \"task iterable must not be null\"));","typeGuard":null,"tryCatchPattern":"try { while (it.hasNext()) it.next(); } catch (RuntimeException e) { Throwable cause = e.getCause(); /* handle real cause */ }","preventionTips":["Wrap checked exceptions inside tasks as RuntimeExceptions","Keep worker iterables free of IO failures via retries","Close ParallelIterables promptly to limit executor pressure"],"tags":["parallel","iteration","checked-exception"],"backgroundTag":"internal-invariant-violation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}