quarkusio/quarkus · error · IllegalStateException

This executor is managed by the container and cannot be shut

Error message

This executor is managed by the container and cannot be shut down.

What it means

The container-managed executor exposed to applications is wrapped in a SmallRyeManagedExecutor whose shutdown() is overridden to throw IllegalStateException, because Quarkus owns the executor lifecycle and shutting it down would break the whole application. Shutdown attempts must go through container shutdown, not application code.

Source

Thrown at extensions/smallrye-context-propagation/runtime/src/main/java/io/quarkus/smallrye/context/runtime/SmallRyeContextPropagationRecorder.java:177

            @Override
            public void run() {
                contextManagerProvider.releaseContextManager(contextManager);
            }
        });
        //Avoid leaking the classloader:
        SmallRyeContextPropagationRecorder.builder = null;
    }

    public Supplier<Object> initializeManagedExecutor(ExecutorService executorService) {
        return new Supplier<Object>() {
            @Override
            public Object get() {
                ThreadContext threadContext = Arc.container().instance(ThreadContext.class).get();
                return new SmallRyeManagedExecutor(-1, -1, (SmallRyeThreadContext) threadContext, executorService,
                        "no-ip") {
                    @Override
                    public void shutdown() {
                        throw new IllegalStateException("This executor is managed by the container and cannot be shut down.");
                    }

                    @Override
                    public List<Runnable> shutdownNow() {
                        throw new IllegalStateException("This executor is managed by the container and cannot be shut down.");
                    }
                };
            }
        };
    }

    public Supplier<Object> initializeConfiguredThreadContext(String[] cleared, String[] propagated, String[] unchanged) {
        return new Supplier<Object>() {
            @Override
            public Object get() {
                return ThreadContext.builder().propagated(propagated).cleared(cleared).unchanged(unchanged).build();
            }
        };

View on GitHub (pinned to e1c734241f)

Solutions

  1. Remove the shutdown() call — the container shuts the executor down itself
  2. If you need an application-owned executor, create your own ManagedExecutor via ManagedExecutorBuilder/instance config rather than the container one
  3. Pass your own executor to third-party libraries that call shutdown on what they are given

Example fix

// before
@Inject ManagedExecutor executor;
void cleanup() { executor.shutdown(); }
// after
void cleanup() {
    // no shutdown needed: container-managed
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (executor instanceof SmallRyeManagedExecutor sme && "no-ip".equals(sme.getName())) {
    throw new IllegalStateException("Do not shut down container-managed executor");
}

Try / catch

try { executor.shutdown(); }
catch (IllegalStateException e) { /* expected: container-managed — remove this call */ }

Prevention

When it happens

Trigger: Calling shutdown() on the managed executor injected via ManagedExecutor/ThreadContext CDI beans provided by the context propagation extension (the 'no-ip' container executor).

Common situations: Porting code that shuts down its own executor into Quarkus; cleanup code in a filter or @PreDestroy calling shutdown on the injected ManagedExecutor; libraries that manage lifecycle of executors passed to them.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f901b58930985f93. Report an issue: GitHub.