Home โบ Java exceptions โบ RejectedExecutionException
RejectedExecutionException: causes and fixes
An executor refused a task because it was shut down or its queue and threads were full.
What it looks like
java.util.concurrent.RejectedExecutionException: Task ... rejected from java.util.concurrent.ThreadPoolExecutor[Running, pool size = 10, active threads = 10, queued tasks = 100, completed tasks = 5321]Extends RuntimeException in java.util.concurrent.
What it means
A ThreadPoolExecutor applies its rejection policy when it cannot accept a task: either it has been shut down, or all threads are busy and the bounded queue is full. The default policy, AbortPolicy, throws RejectedExecutionException. The message prints the pool state, which tells you which of the two situations you are in: "Terminated" or "Shutting down" versus "Running" with a full queue.
Common causes
- Submitting work after
shutdown(), often during application shutdown. - A producer faster than the consumers, filling a bounded queue.
- Too few threads for the workload, or tasks that block for long.
- A pool created per request and never shut down, or a misconfigured Spring
ThreadPoolTaskExecutor.
How to fix it
- If the pool is shut down, stop submitting during shutdown and let in-flight work finish.
- If the queue is full, apply backpressure: slow the producer, use
CallerRunsPolicy, or size the pool and queue from measured load. - Shorten tasks or move blocking calls to a separate pool.
- Monitor queue size and active threads so you see saturation before it rejects work.
Broken and fixed
ExecutorService ex = Executors.newFixedThreadPool(4);
ex.shutdown();
ex.submit(task); // rejectedThreadPoolExecutor ex = new ThreadPoolExecutor(4, 4, 0, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100),
new ThreadPoolExecutor.CallerRunsPolicy());๐ Unravel the failing code ๐ Unravel the fix
In Spring and enterprise code
Spring's @Async uses a task executor with an unbounded queue by default in Boot 3.x unless configured; setting spring.task.execution.pool.queue-capacity introduces rejection.
Debug it faster
Paste the whole stack trace into the stack trace beautifier to hide framework frames, jump to the root cause and find the first line of your own code. It runs in your browser, so the trace never leaves your machine.
Frequently asked questions
Is RejectedExecutionException a checked or unchecked exception?
RejectedExecutionException is an unchecked exception (it extends RuntimeException), so you are not forced to catch it. Prevent it with validation, or handle it where the input enters the system.
Which package is RejectedExecutionException in?
It lives in java.util.concurrent, so the import is import java.util.concurrent.RejectedExecutionException;.
What is the first thing to check when I see RejectedExecutionException?
Read the message and the first stack trace line in your own code. The usual causes are: Submitting work after shutdown(), often during application shutdown; and A producer faster than the consumers, filling a bounded queue.