{"record":{"id":"d84ac36025e7133d","repo":"apache/shenyu","slug":"executor-is-shutdown","errorCode":null,"errorMessage":"Executor is shutdown!","messagePattern":"Executor is shutdown!","errorType":"exception","errorClass":"RejectedExecutionException","httpStatus":null,"severity":"error","filePath":"shenyu-common/src/main/java/org/apache/shenyu/common/concurrent/TaskQueue.java","lineNumber":85,"sourceCode":"     *\n     * @param e the element to add\n     * @return {@code true} if the element was added to this queue, else {@code false}\n     */\n    boolean doOffer(E e);\n\n    /**\n     * retry offer task.\n     *\n     * @param o       task\n     * @param timeout timeout\n     * @param unit    timeout unit\n     * @return offer success or not\n     * @throws java.util.concurrent.RejectedExecutionException if executor is terminated.\n     * @throws java.lang.InterruptedException                  if the current thread is interrupted.\n     */\n    default boolean retryOffer(final E o, final long timeout, final TimeUnit unit) throws InterruptedException {\n        if (getExecutor().isShutdown()) {\n            throw new RejectedExecutionException(\"Executor is shutdown!\");\n        }\n        return offer(o, timeout, unit);\n    }\n}\n","sourceCodeStart":67,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-common/src/main/java/org/apache/shenyu/common/concurrent/TaskQueue.java#L67-L90","documentation":"TaskQueue.retryOffer() first checks getExecutor().isShutdown() and throws RejectedExecutionException('Executor is shutdown!') to avoid offering tasks into a terminated executor. It is the retry path used by ShenyuThreadPoolExecutor.execute() after pool rejection, so this surfaces when tasks are submitted during or after shutdown.","triggerScenarios":"retryOffer(o, timeout, unit) called (directly or via execute()'s rejection-retry) while the executor has been shut down but tasks are still being submitted.","commonSituations":"Application shutdown (Spring context close) racing with background producers still submitting; calling shutdown() early in code while scheduled producers keep running.","solutions":["Stop producers before calling executor.shutdown() (e.g. dispose upstream schedulers/threads first).","Guard submission with an isShutdown check or a lifecycle flag at the call site.","Catch RejectedExecutionException during shutdown windows and treat it as expected.","Use shutdown-gracefully patterns: awaitTermination after shutdown before declaring the pipeline closed."],"exampleFix":"// before\nexecutor.shutdown();\nproducer.submit(task); // may throw 'Executor is shutdown!'\n// after\nproducer.stop();\nexecutor.shutdown();\nexecutor.awaitTermination(30, TimeUnit.SECONDS);","handlingStrategy":"try-catch","validationCode":"if (executor.isShutdown()) {\n    LOG.warn(\"executor already shut down, skipping submission\");\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    executor.execute(task);\n} catch (RejectedExecutionException e) {\n    if (executor.isShutdown()) {\n        LOG.info(\"Task dropped due to orderly shutdown\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Stop all producers before shutdown(); use application lifecycle hooks.","Treat RejectedExecutionException during shutdown as expected, not fatal.","Use awaitTermination to confirm drain before process exit."],"tags":["concurrency","thread-pool","shutdown","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}