apache/iceberg · error · RuntimeException
Task set failed with an uncaught throwable
Error message
Task set failed with an uncaught throwable
What it means
Tasks (single-threaded execution path) collects task failures; if a task threw a Throwable that is not an Exception (so it escaped the exception-collection logic, caught via 'threw'), and throwFailureWhenFinished is set and the exceptions list is empty, it throws this RuntimeException. It signals a non-Exception throwable (e.g. Error, or a Throwable subclass) killed the task set without being recorded as a normal failure.
Solutions
- Inspect the task's original stack trace/logs — this wrapper hides a non-Exception throwable; find the underlying Error
- Fix the root cause (classpath, memory, or bad throwable usage in task code)
- Ensure task code throws Exception/RuntimeException subtypes so failures are collected and reported via throwOne
- If failures should be tolerated, drop throwFailureWhenFinished or add .suppress()/.retry() configuration
Example fix
// before
Tasks.foreach(items).throwFailureWhenFinished().run(item -> process(item)); // process throws Error
// after
Tasks.foreach(items).throwFailureWhenFinished().run(item -> {
try { process(item); } catch (Throwable t) {
throw new RuntimeException("processing failed for " + item, t); // surface as collected failure
}
}); Defensive patterns
Strategy: try-catch
Try / catch
boolean ok = Tasks.foreach(items)
.suppress()
.run(task);
if (!ok) { /* inspect logs for the non-Exception throwable */ } Prevention
- Throw Exception/RuntimeException subtypes from task bodies, never Throwable/Error
- Monitor JVM Error conditions (OOM, stack overflow) in task threads
- Keep the original task stack traces in logs
- Use suppress()/retry() deliberately rather than relying on abort semantics
When it happens
Trigger: Running Tasks.foreach(...).throwFailureWhenFinished() where a task threw a Throwable that is not an Exception (e.g. StackOverflowError, NoClassDefFoundError, or a custom Throwable), bypassing the exceptions list.
Common situations: Classpath issues surfacing as Error during task execution; OOM/stack overflow inside task bodies; throwing Throwable subclasses from custom task implementations.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bf633819877e9b2b.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/util/Tasks.java:278
try {
abortTask.run(iterator.next());
} catch (Exception e) {
failed = true;
LOG.error("Failed to abort task", e);
// keep going
}
if (stopAbortsOnFailure && failed) {
break;
}
}
}
}
}
if (throwFailureWhenFinished && !exceptions.isEmpty()) {
Tasks.throwOne(exceptions, exceptionClass);
} else if (throwFailureWhenFinished && threw) {
throw new RuntimeException("Task set failed with an uncaught throwable");
}
return !threw;
}
private void tryRunOnFailure(I item, Exception failure) {
try {
onFailure.run(item, failure);
} catch (Exception failException) {
failure.addSuppressed(failException);
LOG.error("Failed to clean up on failure", failException);
// keep going
}
}
private <E extends Exception> boolean runParallel(
final Task<I, E> task, Class<E> exceptionClass) throws E {
final Queue<I> succeeded = new ConcurrentLinkedQueue<>();View on GitHub (pinned to 86d9c8fc54)