apache/flink · warning · CancellationException

Task has been cancelled.

Error message

Task has been cancelled.

What it means

DirectExecutorService runs tasks on the caller thread; when a Future returned by its submit-family methods is cancelled before execution, it hands back a Future whose get() throws CancellationException with this message. The future reports isCancelled()==true and isDone()==false, so any blocking get() is required to fail per the java.util.concurrent contract.

Source

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

                    new Future<T>() {
                        @Override
                        public boolean cancel(boolean mayInterruptIfRunning) {
                            return false;
                        }

                        @Override
                        public boolean isCancelled() {
                            return true;
                        }

                        @Override
                        public boolean isDone() {
                            return false;
                        }

                        @Override
                        public T get() {
                            throw new CancellationException("Task has been cancelled.");
                        }

                        @Override
                        public T get(long timeout, @Nonnull TimeUnit unit) {
                            throw new CancellationException("Task has been cancelled.");
                        }
                    });
        }

        return result;
    }

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

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Check future.isCancelled() before calling get().
  2. Catch CancellationException where cancellation is an expected outcome and handle it as control flow, not an error.
  3. Avoid cancelling tasks whose results you still intend to consume.

Example fix

// before
T result = future.get();

// after
if (future.isCancelled()) {
    return; // task was cancelled; nothing to retrieve
}
T result = future.get();
Defensive patterns

Strategy: try-catch

Validate before calling

if (future.isCancelled()) { /* skip get() */ }

Try / catch

try { T v = future.get(); }
catch (CancellationException e) { /* cancelled: normal control flow, abort dependent work */ }

Prevention

When it happens

Trigger: Calling future.get() on a Future obtained from DirectExecutorService (e.g. via submit then cancel, or the completed/cancelled future wrappers) after cancellation.

Common situations: Test code using DirectExecutorService to simulate async behavior then asserting on cancelled futures; cancellation of probes/tasks in components that run with the direct executor during shutdown; generic code that blocks on futures without checking isCancelled().

Related errors


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