PhilJay/MPAndroidChart · error · IllegalArgumentException

The object to recycle already belongs to poolId

Error message

The object to recycle already belongs to poolId {object.currentOwnerId}.  Object cannot belong to two different pool instances simultaneously!

What it means

Thrown by ObjectPool.recycle(T) when the object belongs to a different pool (currentOwnerId != NO_OWNER and != this.poolId). A Poolable can only be owned by one pool at a time; recycling it into another pool would violate that invariant. The offending poolId is interpolated into the message.

Solutions

  1. Recycle each object into the exact pool that produced it (track owner via pool.getPoolId()).
  2. Maintain a single pool per object type instead of multiple pools.
  3. Before cross-pool handoff, ensure the object is NO_OWNER (it already is once acquired); do not recycle into a foreign pool.
  4. Tag acquired objects with their source pool id and assert on recycle.

Example fix

// before
Poolable o = poolA.get();
poolB.recycle(o); // throws: belongs to poolA

// after
Poolable o = poolA.get();
poolA.recycle(o); // return to the owner pool
Defensive patterns

Strategy: validation

Validate before calling

if (object.currentOwnerId == Poolable.NO_OWNER || object.currentOwnerId == pool.getPoolId()) {
    pool.recycle(object);
} else {
    Log.w(TAG, "Object belongs to pool " + object.currentOwnerId);
}

Type guard

boolean belongsToPool(Poolable o, ObjectPool pool) {
    return o.currentOwnerId == pool.getPoolId();
}

Prevention

When it happens

Trigger: Acquiring an object from poolA and recycling it into poolB. Sharing Poolable subtypes across two pool instances. Reassigning an object to a newly created pool without releasing it from the old one.

Common situations: Multiple pools for the same type (e.g. one per chart); refactoring that introduced a second pool but reused old objects; cross-thread object handoff where each thread has its own pool.

Related errors


AI-assisted analysis of PhilJay/MPAndroidChart@9c7275a059 (2026-08-14). Data as JSON: /api/errors/b72fc57f06a48b92. Report an issue: GitHub.

Appendix: source

Thrown at MPChartLib/src/main/java/com/github/mikephil/charting/utils/ObjectPool.java:137

        T result = (T)objects[this.objectsPointer];
        result.currentOwnerId = Poolable.NO_OWNER;
        this.objectsPointer--;

        return result;
    }

    /**
     * Recycle an instance of Poolable that this pool is capable of generating.
     * The T instance passed must not already exist inside this or any other ObjectPool instance.
     *
     * @param object An object of type T to recycle
     */
    public synchronized void recycle(T object){
        if(object.currentOwnerId != Poolable.NO_OWNER){
            if(object.currentOwnerId == this.poolId){
                throw new IllegalArgumentException("The object passed is already stored in this pool!");
            }else {
                throw new IllegalArgumentException("The object to recycle already belongs to poolId " + object.currentOwnerId + ".  Object cannot belong to two different pool instances simultaneously!");
            }
        }

        this.objectsPointer++;
        if(this.objectsPointer >= objects.length){
            this.resizePool();
        }

        object.currentOwnerId = this.poolId;
        objects[this.objectsPointer] = object;

    }

    /**
     * Recycle a List of Poolables that this pool is capable of generating.
     * The T instances passed must not already exist inside this or any other ObjectPool instance.
     *
     * @param objects A list of objects of type T to recycle

View on GitHub (pinned to 9c7275a059)