nostra13/Android-Universal-Image-Loader · warning · IllegalStateException

Deque full

Error message

Deque full

What it means

The collection constructor of this backported LinkedBlockingDeque throws IllegalStateException("Deque full") while copying elements if linkLast() fails, i.e. the number of source elements exceeds the deque's capacity (initialized here to Integer.MAX_VALUE). This class is an Android-compatible copy of java.util.concurrent.LinkedBlockingDeque used internally by UIL's task queues; in practice the default capacity makes this unreachable unless a bounded capacity was set.

Source

Thrown at library/src/main/java/com/nostra13/universalimageloader/core/assist/deque/LinkedBlockingDeque.java:185

     * Creates a {@code LinkedBlockingDeque} with a capacity of
     * {@link Integer#MAX_VALUE}, initially containing the elements of
     * the given collection, added in traversal order of the
     * collection's iterator.
     *
     * @param c the collection of elements to initially contain
     * @throws NullPointerException if the specified collection or any
     *                              of its elements are null
     */
    public LinkedBlockingDeque(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        final ReentrantLock lock = this.lock;
        lock.lock(); // Never contended, but necessary for visibility
        try {
            for (E e : c) {
                if (e == null)
                    throw new NullPointerException();
                if (!linkLast(new Node<E>(e)))
                    throw new IllegalStateException("Deque full");
            }
        } finally {
            lock.unlock();
        }
    }


    // Basic linking and unlinking operations, called only while holding lock

    /**
     * Links node as first element, or returns false if full.
     */
    private boolean linkFirst(Node<E> node) {
        // assert lock.isHeldByCurrentThread();
        if (count >= capacity)
            return false;
        Node<E> f = first;
        node.next = f;

View on GitHub (pinned to ba33ec64d0)

Solutions

  1. Size the capacity to at least the collection size: new LinkedBlockingDeque<>(Math.max(capacity, c.size()))
  2. Or use the unbounded default constructor before adding elements
  3. Prefer java.util.concurrent.LinkedBlockingDeque on API 9+ instead of this backport

Example fix

// before
LinkedBlockingDeque<Runnable> q =
        new LinkedBlockingDeque<Runnable>(16);
q = new LinkedBlockingDeque<Runnable>(q); // growing later may exceed 16 -> Deque full

// after
LinkedBlockingDeque<Runnable> q =
        new LinkedBlockingDeque<Runnable>(Math.max(16, source.size()));
Defensive patterns

Strategy: validation

Validate before calling

int cap = Math.max(desiredCapacity, sourceCollection.size());
LinkedBlockingDeque<Runnable> q = new LinkedBlockingDeque<Runnable>(cap);
for (Runnable r : sourceCollection) q.addLast(r);

Prevention

When it happens

Trigger: new LinkedBlockingDeque<>(hugeCollection) with a capacity set via this(Integer.MAX_VALUE) is effectively unbounded; reachable only if the class is instantiated with a small capacity elsewhere and then filled from a larger collection. Library users hit it only if they directly instantiate this backport with a bound.

Common situations: Custom code instantiating the backported deque with an explicit capacity and copy-constructing from a bigger collection; migration code converting queues during configuration changes.

Related errors


AI-assisted analysis of nostra13/Android-Universal-Image-Loader@ba33ec64d0 (2026-08-14). Data as JSON: /api/errors/0f2047bec6ea1cf4. Report an issue: GitHub.