BackendBench
Coffee

Home โ€บ Java exceptions โ€บ RejectedExecutionException

Unchecked exception ยท java.util.concurrent

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

How to fix it

  1. If the pool is shut down, stop submitting during shutdown and let in-flight work finish.
  2. If the queue is full, apply backpressure: slow the producer, use CallerRunsPolicy, or size the pool and queue from measured load.
  3. Shorten tasks or move blocking calls to a separate pool.
  4. Monitor queue size and active threads so you see saturation before it rejects work.

Broken and fixed

fails
ExecutorService ex = Executors.newFixedThreadPool(4);
ex.shutdown();
ex.submit(task); // rejected
works
ThreadPoolExecutor 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.

Related exceptions

More tools you might need