apache/shenyu · error · RejectedExecutionException

Executor is shutdown!

Error message

Executor is shutdown!

What it means

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.

Solutions

  1. Stop producers before calling executor.shutdown() (e.g. dispose upstream schedulers/threads first).
  2. Guard submission with an isShutdown check or a lifecycle flag at the call site.
  3. Catch RejectedExecutionException during shutdown windows and treat it as expected.
  4. Use shutdown-gracefully patterns: awaitTermination after shutdown before declaring the pipeline closed.

Example fix

// before
executor.shutdown();
producer.submit(task); // may throw 'Executor is shutdown!'
// after
producer.stop();
executor.shutdown();
executor.awaitTermination(30, TimeUnit.SECONDS);
Defensive patterns

Strategy: try-catch

Validate before calling

if (executor.isShutdown()) {
    LOG.warn("executor already shut down, skipping submission");
    return;
}

Try / catch

try {
    executor.execute(task);
} catch (RejectedExecutionException e) {
    if (executor.isShutdown()) {
        LOG.info("Task dropped due to orderly shutdown");
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Application shutdown (Spring context close) racing with background producers still submitting; calling shutdown() early in code while scheduled producers keep running.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/d84ac36025e7133d. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-common/src/main/java/org/apache/shenyu/common/concurrent/TaskQueue.java:85

     *
     * @param e the element to add
     * @return {@code true} if the element was added to this queue, else {@code false}
     */
    boolean doOffer(E e);

    /**
     * retry offer task.
     *
     * @param o       task
     * @param timeout timeout
     * @param unit    timeout unit
     * @return offer success or not
     * @throws java.util.concurrent.RejectedExecutionException if executor is terminated.
     * @throws java.lang.InterruptedException                  if the current thread is interrupted.
     */
    default boolean retryOffer(final E o, final long timeout, final TimeUnit unit) throws InterruptedException {
        if (getExecutor().isShutdown()) {
            throw new RejectedExecutionException("Executor is shutdown!");
        }
        return offer(o, timeout, unit);
    }
}

View on GitHub (pinned to 567142e072)