apache/dubbo · error · RejectedExecutionException
Queue capacity is full.
Error message
Queue capacity is full.
What it means
Thrown by EagerThreadPoolExecutor.execute() when the executor's initial super.execute() rejects the task AND the subsequent retryOffer() into the TaskQueue also fails (returns false). The EagerThreadPool is designed to create threads eagerly up to max before queuing; this error means even the fallback queue-offer failed — the pool is at maximum threads AND the queue is at capacity. This is a sibling of the standard thread-pool-exhausted scenario but specific to the 'eager' thread pool type.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutor.java:51
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
@Override
public void execute(Runnable command) {
if (command == null) {
throw new NullPointerException();
}
try {
super.execute(command);
} catch (RejectedExecutionException rx) {
// retry to offer the task into queue.
final TaskQueue queue = (TaskQueue) super.getQueue();
try {
if (!queue.retryOffer(command, 0, TimeUnit.MILLISECONDS)) {
throw new RejectedExecutionException("Queue capacity is full.", rx);
}
} catch (InterruptedException x) {
throw new RejectedExecutionException(x);
}
}
}
}
View on GitHub (pinned to 3a3043227f)
Solutions
- Increase the eager thread pool's max threads (threads parameter) and/or queue capacity (queued parameter / queue capacity).
- Switch to 'fixed' or 'cached' thread pool if eager semantics aren't required, to simplify capacity reasoning.
- Reduce task execution time or move blocking work off the Dubbo thread pool to a dedicated executor.
- Scale providers horizontally to distribute load.
Example fix
// before — eager pool with small queue @dubbo.Service(threadpool = "eager", threads = 100) // after — larger threads and queue capacity @dubbo.Service(threadpool = "eager", threads = 300, queues = 1000)
Defensive patterns
Strategy: try-catch
Validate before calling
// Check eager pool capacity before submit
EagerThreadPoolExecutor eagerPool = (EagerThreadPoolExecutor) pool;
int queueCap = ((TaskQueue<?>) eagerPool.getQueue()).remainingCapacity() + eagerPool.getQueue().size();
boolean canAccept = !eagerPool.isShutdown()
&& (eagerPool.getActiveCount() < eagerPool.getMaximumPoolSize()
|| ((TaskQueue<?>) eagerPool.getQueue()).remainingCapacity() > 0);
if (!canAccept) {
applyBackpressure();
} Try / catch
try {
pool.execute(task);
} catch (RejectedExecutionException e) {
if (e.getMessage().contains("Queue capacity is full")) {
logger.warn("Eager pool queue full, backing off", e);
backoffAndRetry(task); // exponential backoff or external queue
} else {
throw e;
}
} Prevention
- Size the eager pool's threads and queue capacity for peak load.
- Set Dubbo timeout to prevent slow tasks from consuming threads.
- Use a larger queue capacity (queues parameter) for burst tolerance.
- Monitor eager pool metrics (active, queue size) and alert before saturation.
When it happens
Trigger: Using threadpool='eager' configuration: all threads are at maximumPoolSize and the TaskQueue.retryOffer(command, 0, MILLISECONDS) returns false because the underlying LinkedBlockingQueue is full at capacity with zero timeout. This is a transient or sustained overload condition on an eager pool.
Common situations: Eager thread pool (threadpool=eager) undersized for load; the TaskQueue capacity is set too low; burst traffic that exceeds both thread creation and queue capacity; slow tasks filling the queue faster than workers drain it.
Related errors
- Thread pool is EXHAUSTED! Thread Name: %s, Pool Size: %d (ac
- The task queue does not have executor!
- Executor is shutdown!
- no more memory can be used !
- Number of pending timeouts ({}) is greater than or equal to
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/381166c1710e3fbb.
Report an issue: GitHub.