{"record":{"id":"3fa5260dadecd2c5","repo":"quarkusio/quarkus","slug":"shutdown-not-allowed-on-managed-executor-service","errorCode":null,"errorMessage":"shutdown not allowed on managed executor service","messagePattern":"shutdown not allowed on managed executor service","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"extensions/virtual-threads/runtime/src/main/java/io/quarkus/virtual/threads/DelegatingExecutorService.java","lineNumber":39,"sourceCode":"        return delegate;\n    }\n\n    public boolean isShutdown() {\n        // container managed executors are never shut down from the application's perspective\n        return false;\n    }\n\n    public boolean isTerminated() {\n        // container managed executors are never shut down from the application's perspective\n        return false;\n    }\n\n    public boolean awaitTermination(final long timeout, final TimeUnit unit) {\n        return false;\n    }\n\n    public void shutdown() {\n        throw new UnsupportedOperationException(\"shutdown not allowed on managed executor service\");\n    }\n\n    public List<Runnable> shutdownNow() {\n        throw new UnsupportedOperationException(\"shutdownNow not allowed on managed executor service\");\n    }\n\n    public String toString() {\n        return delegate.toString();\n    }\n}\n","sourceCodeStart":21,"sourceCodeEnd":50,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/virtual-threads/runtime/src/main/java/io/quarkus/virtual/threads/DelegatingExecutorService.java#L21-L50","documentation":"DelegatingExecutorService wraps a Quarkus-managed executor (backed by virtual threads or the container-managed thread pool). Because the lifecycle of the underlying executor is owned by Quarkus, callers must not shut it down; shutdown() therefore throws UnsupportedOperationException unconditionally.","triggerScenarios":"Invoking shutdown() on the ExecutorService returned by Quarkus' managed executor injection or the virtual-threads support (e.g. from an @ApplicationScoped bean holding the executor and attempting cleanup in @PreDestroy/stop logic).","commonSituations":"Application shutdown hooks or library code (e.g. closing a client that accepts an ExecutorService) that calls executor.shutdown() out of habit on an injected managed executor.","solutions":["Remove the shutdown()/shutdownNow() call — Quarkus shuts the executor down itself","Inject/accept a dedicated application-owned ExecutorService (e.g. Executors.newVirtualThreadPerTaskExecutor()) where lifecycle shutdown is required","Wrap the managed executor so consuming third-party code never sees lifecycle methods"],"exampleFix":"// before\n@PreDestroy\nvoid stop() { executor.shutdown(); } // UnsupportedOperationException\n// after\n@PreDestroy\nvoid stop() { /* managed by Quarkus; nothing to do */ }","handlingStrategy":"validation","validationCode":"if (executor instanceof DelegatingExecutorService || isQuarkusManaged(executor)) { /* skip shutdown */ }","typeGuard":"boolean isManagedExecutor(ExecutorService es) { return es.getClass().getName().startsWith(\"io.quarkus.virtual.threads\"); }","tryCatchPattern":"try { executor.shutdown(); } catch (UnsupportedOperationException ignored) { /* managed by Quarkus */ }","preventionTips":["Never call shutdown/shutdownNow on injected Quarkus executors","Do not pass managed executors to libraries that close their ExecutorService","Provide a dedicated executor to third-party code that requires lifecycle control"],"tags":["virtual-threads","executor","lifecycle","unsupported-operation"],"backgroundTag":"shutdown-not-allowed-on-managed-executor","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}