apache/cassandra · error · RejectedExecutionException
${executor} has shut down
Error message
${executor} has shut down What it means
Thrown as a RejectedExecutionException by ThreadPoolExecutorBase when a task is submitted to an executor that has already been shut down. The submission loop first checks executor.isShutdown() and rejects rather than queueing into a dead pool.
Source
Thrown at src/java/org/apache/cassandra/concurrent/ThreadPoolExecutorBase.java:54
* <li>Tasks rejected due to overflow of the queue block the submitting thread rather than throwing {@link RejectedExecutionException}
* <li>{@link RunnableFuture} rejected due to executor shutdown will be cancelled
* <li>{@link RunnableFuture} removed by {@link #shutdownNow()} will be cancelled
*
* We also provide a shutdown hook for JMX registration cleanup.
*/
public class ThreadPoolExecutorBase extends ThreadPoolExecutor implements ResizableThreadPool
{
public static final RejectedExecutionHandler blockingExecutionHandler = (task, executor) ->
{
BlockingQueue<Runnable> queue = executor.getQueue();
try
{
while (true)
{
try
{
if (executor.isShutdown())
throw new RejectedExecutionException(executor + " has shut down");
if (queue.offer(task, 1, TimeUnit.SECONDS))
break;
}
catch (InterruptedException e)
{
throw new UncheckedInterruptedException(e);
}
}
}
catch (Throwable t)
{
//Give some notification to the caller the task isn't going to run
if (task instanceof java.util.concurrent.Future)
((java.util.concurrent.Future<?>) task).cancel(false);
throw t;
}
};View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Stop producers before calling shutdown(), or add a terminated flag producers check before submitting
- Catch RejectedExecutionException around submit and treat it as 'dropped during shutdown'
- Use a longer-lived executor or delay shutdown until pending work completes
- Guard submissions with ExecutorService.isShutdown() checks at the call site
Example fix
// before
executor.submit(() -> handle(message));
// after
try
{
executor.submit(() -> handle(message));
}
catch (RejectedExecutionException e)
{
logger.debug("Executor shut down, dropping task", e);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (executor.isShutdown()) { logger.warn("Executor shut down; skipping submit"); return; } Try / catch
try {
executor.submit(task);
} catch (RejectedExecutionException e) {
logger.debug("Task dropped because executor shut down", e);
} Prevention
- Stop task producers before calling shutdown()
- Track executor lifecycle with a volatile terminated flag
- Treat RejectedExecutionException as benign during shutdown paths
When it happens
Trigger: Calling executor.execute()/submit() after shutdown() or shutdownNow() was invoked, typically during node shutdown, decommission, or stop of a service holding the executor.
Common situations: Background daemons or callbacks firing during Cassandra shutdown, tests tearing down clusters while async work is still submitting, race between a scheduler and lifecycle shutdown hooks.
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
- threadGroup may only be overridden with a child of the defau
- Queue is empty
- UnsupportedOperationException
- Maximum pool size has been changed while resizing
- ${executor.name} not terminated
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/9e14119218b671cb.
Report an issue: GitHub.