apache/flink · error · ExecutionException

No tasks finished successfully.

Error message

No tasks finished successfully.

What it means

DirectExecutorService.invokeAny executes callables one by one on the calling thread and returns the first success. If every callable throws, it wraps the LAST observed exception in an ExecutionException with this message. This mirrors the standard ExecutorService.invokeAny contract for the all-failed case.

Source

Thrown at flink-core/src/main/java/org/apache/flink/util/concurrent/DirectExecutorService.java:211

    @Override
    @Nonnull
    public <T> T invokeAny(@Nonnull Collection<? extends Callable<T>> tasks)
            throws ExecutionException {
        throwRejectedExecutionExceptionIfShutdown();

        Exception exception = null;

        for (Callable<T> task : tasks) {
            try {
                return task.call();
            } catch (Exception e) {
                // try next task
                exception = e;
            }
        }

        throw new ExecutionException("No tasks finished successfully.", exception);
    }

    @Override
    public <T> T invokeAny(
            @Nonnull Collection<? extends Callable<T>> tasks, long timeout, @Nonnull TimeUnit unit)
            throws ExecutionException, TimeoutException {
        throwRejectedExecutionExceptionIfShutdown();

        long end = System.currentTimeMillis() + unit.toMillis(timeout);
        Exception exception = null;

        Iterator<? extends Callable<T>> iterator = tasks.iterator();

        while (end > System.currentTimeMillis() && iterator.hasNext()) {
            Callable<T> callable = iterator.next();

            try {
                return callable.call();

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Inspect getCause() of the ExecutionException — it is the last task's exception, which is usually the most informative starting point.
  2. Fix or make reachable at least one of the underlying resources/callables.
  3. If you need all failure causes, replace invokeAny with per-task submit and collect exceptions yourself.

Example fix

// before
try { service.invokeAny(tasks); } catch (ExecutionException e) { log.error("failed"); }

// after
try { service.invokeAny(tasks); }
catch (ExecutionException e) { log.error("all tasks failed, last cause:", e.getCause()); }
Defensive patterns

Strategy: try-catch

Try / catch

try { T r = executor.invokeAny(tasks); }
catch (ExecutionException e) { Throwable root = e.getCause(); /* handle last task's failure */ }

Prevention

When it happens

Trigger: Calling invokeAny(tasks) where tasks is non-empty and every Callable.call() throws; the returned exception's cause is the final task's exception, earlier ones are lost.

Common situations: Failover/retry helpers that try a list of replicas or strategies with the direct executor; unit tests simulating all-backends-down; missing the fact that only the last cause is preserved when debugging.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/95926d8e808d4036. Report an issue: GitHub.