{"record":{"id":"1739254003d5c090","repo":"apache/dubbo","slug":"executor-is-shutdown","errorCode":null,"errorMessage":"Executor is shutdown!","messagePattern":"Executor is shutdown!","errorType":"exception","errorClass":"RejectedExecutionException","httpStatus":null,"severity":"warning","filePath":"dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/TaskQueue.java","lineNumber":74,"sourceCode":"        // return false to let executor create new worker.\n        if (currentPoolThreadSize < executor.getMaximumPoolSize()) {\n            return false;\n        }\n\n        // currentPoolThreadSize >= max\n        return super.offer(runnable);\n    }\n\n    /**\n     * retry offer task\n     *\n     * @param o task\n     * @return offer success or not\n     * @throws RejectedExecutionException if executor is terminated.\n     */\n    public boolean retryOffer(Runnable o, long timeout, TimeUnit unit) throws InterruptedException {\n        if (executor.isShutdown()) {\n            throw new RejectedExecutionException(\"Executor is shutdown!\");\n        }\n        return super.offer(o, timeout, unit);\n    }\n}\n","sourceCodeStart":56,"sourceCodeEnd":79,"githubUrl":"https://github.com/apache/dubbo/blob/3a3043227f5571d25eb2889de5bca22f2914843b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/TaskQueue.java#L56-L79","documentation":"Thrown by TaskQueue.retryOffer() when the associated executor's isShutdown() returns true. retryOffer() is called by EagerThreadPoolExecutor.execute() as a fallback after the initial submit is rejected — if the pool has been shut down in the meantime (or was already shutting down), retrying the offer is pointless and this RejectedExecutionException is thrown instead of silently dropping the task.","triggerScenarios":"Submitting a task to an EagerThreadPoolExecutor that is in the process of shutting down (shutdown() has been called). The initial execute() is rejected (e.g., pool saturated during shutdown), the retry path checks isShutdown(), finds it true, and throws. Also occurs if tasks are submitted from a shutdown hook or during application teardown.","commonSituations":"Application shutdown race — tasks submitted while the Dubbo framework or a custom executor is shutting down; shutdown hooks triggering invocations; reactive/async pipelines that outlive the executor's lifecycle; resource cleanup ordering issues.","solutions":["Ensure no new tasks are submitted after executor.shutdown() — coordinate shutdown with an 'accepting' flag checked before submit.","Use executor.awaitTermination() in your shutdown sequence and stop submitting before calling shutdown().","Catch RejectedExecutionException at the submission site and treat it as a shutdown signal (log and discard or queue for retry on restart).","Fix resource lifecycle ordering so the Dubbo/client subsystem is fully drained before the executor is shut down."],"exampleFix":"// before — submitting during shutdown\nvolatile boolean accepting = true;\n// ... shutdown path calls executor.shutdown() ...\nexecutor.execute(task); // throws if shutdown in progress\n\n// after — check accepting flag before submit\nif (!accepting || executor.isShutdown()) {\n    handleGracefulRejection(task);\n    return;\n}\nexecutor.execute(task);","handlingStrategy":"validation","validationCode":"// Check shutdown state before submitting\nif (!executor.isShutdown() && !executor.isTerminated()) {\n    executor.execute(task);\n} else {\n    logger.debug(\"Executor is shutdown, discarding task\");\n    handleShutdownDiscard(task);\n}","typeGuard":null,"tryCatchPattern":"try {\n    executor.execute(task);\n} catch (RejectedExecutionException e) {\n    if (executor.isShutdown()) {\n        logger.debug(\"Task rejected because executor is shutting down\", e);\n        handleShutdownDiscard(task); // log and drop, or persist for later\n    } else {\n        throw e; // genuine capacity issue, not shutdown\n    }\n}","preventionTips":["Coordinate shutdown: stop accepting new work before calling executor.shutdown().","Maintain a volatile 'accepting' flag checked before every submit.","Drain pending work (awaitTermination) before the container/framework fully tears down.","Catch RejectedExecutionException at submit sites and treat shutdown-triggered rejections as non-error."],"tags":["thread-pool","shutdown","lifecycle","rejected-execution"],"backgroundTag":null,"analyzedSha":"3a3043227f5571d25eb2889de5bca22f2914843b","analyzedAt":"2026-08-14T00:43:19.853Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}