{"record":{"id":"77dd342e1dddb007","repo":"grpc/grpc-java","slug":"restricted-shutdownnow-is-not-allowed","errorCode":null,"errorMessage":"Restricted: shutdownNow() is not allowed","messagePattern":"Restricted: shutdownNow\\(\\) is not allowed","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/grpc/internal/ManagedChannelImpl.java","lineNumber":2194,"sourceCode":"\n    @Override\n    public boolean isShutdown() {\n      return delegate.isShutdown();\n    }\n\n    @Override\n    public boolean isTerminated() {\n      return delegate.isTerminated();\n    }\n\n    @Override\n    public void shutdown() {\n      throw new UnsupportedOperationException(\"Restricted: shutdown() is not allowed\");\n    }\n\n    @Override\n    public List<Runnable> shutdownNow() {\n      throw new UnsupportedOperationException(\"Restricted: shutdownNow() is not allowed\");\n    }\n\n    @Override\n    public <T> Future<T> submit(Callable<T> task) {\n      return delegate.submit(task);\n    }\n\n    @Override\n    public Future<?> submit(Runnable task) {\n      return delegate.submit(task);\n    }\n\n    @Override\n    public <T> Future<T> submit(Runnable task, T result) {\n      return delegate.submit(task, result);\n    }\n\n    @Override","sourceCodeStart":2176,"sourceCodeEnd":2212,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java#L2176-L2212","documentation":"Same restricted ExecutorService wrapper as the shutdown() case: shutdownNow() is disabled because the channel owns the executor's lifecycle. Calling it throws UnsupportedOperationException to protect channel invariants.","triggerScenarios":"Calling shutdownNow() on the ExecutorService view handed out by ManagedChannelImpl to internal components (balancers, listeners) during custom cleanup or cancellation paths.","commonSituations":"Custom LoadBalancer teardown code force-stopping all executors it references; generic shutdown hooks iterating over all ExecutorServices in an application.","solutions":["Use channel.shutdownNow() to cancel in-flight work; the channel will manage its executor.","Shut down only the executor instance you originally supplied to the builder.","Exclude the channel-wrapped executor from generic executor cleanup loops."],"exampleFix":"// before\nList<Runnable> pending = executorService.shutdownNow();\n// after\nchannel.shutdownNow();","handlingStrategy":"try-catch","validationCode":"boolean ownsExecutor = createdHere; // track ownership explicitly; never shutdownNow() executors received from gRPC","typeGuard":null,"tryCatchPattern":"try {\n  executor.shutdownNow();\n} catch (UnsupportedOperationException e) {\n  channel.shutdownNow();\n}","preventionTips":["Never include channel-internal executors in generic cleanup loops.","Call channel.shutdownNow() to force-cancel work.","Keep ownership of executor lifecycle with ManagedChannelImpl."],"tags":["grpc","lifecycle","executor","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}