airbnb/epoxy · error · IllegalStateException
A pool was already found
Error message
A pool was already found
What it means
ActivityRecyclerPool caches one RecyclerView.RecycledViewPool per Activity context. When retrieving a pool for a context, if a second pool reference for the same context is encountered during iteration, its internal invariant is broken and this IllegalStateException is thrown.
Solutions
- Ensure the pool is registered at most once per Activity context (guard your registration code)
- Update epoxy-adapter — this indicates corrupted internal state in the pool registry
- As a workaround, construct the pool yourself and pass it to EpoxyRecyclerView instead of relying on ActivityRecyclerPool
Defensive patterns
Strategy: try-catch
Try / catch
try { pool = ActivityRecyclerPool.getPool(activity) } catch (e: IllegalStateException) { pool = RecyclerView.RecycledViewPool() } Prevention
- Register a pool once per Activity
- Update epoxy-adapter to get registry fixes
- Provide your own RecycledViewPool to avoid the shared registry
When it happens
Trigger: getPool(context) finding two pool references whose context === the requested context during iteration — i.e., a pool was registered twice for the same Activity.
Common situations: Re-registering or leaking pool registrations for the same Activity; unusual Activity recreation patterns causing duplicate entries in the internal map.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Must have stable ids when saving view holder state
- State cannot be restored once views have been bound. It…
- Tried to restore instance state, but onSaveInstanceState…
- numItemsToPrefetch must be greater than 0
- Unable to invoke
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/4622aa28a37ee3a3.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/ActivityRecyclerPool.kt:38
* only needs to hold pools for active activities.
*/
private val pools = ArrayList<PoolReference>(5)
@JvmOverloads
fun getPool(
context: Context,
poolFactory: () -> RecyclerView.RecycledViewPool
): PoolReference {
val iterator = pools.iterator()
var poolToUse: PoolReference? = null
while (iterator.hasNext()) {
val poolReference = iterator.next()
when {
poolReference.context === context -> {
if (poolToUse != null) {
throw IllegalStateException("A pool was already found")
}
poolToUse = poolReference
// finish iterating to remove any old contexts
}
poolReference.context.isActivityDestroyed() -> {
// A pool from a different activity that was destroyed.
// Clear the pool references to allow the activity to be GC'd
poolReference.viewPool.clear()
iterator.remove()
}
}
}
if (poolToUse == null) {
poolToUse = PoolReference(context, poolFactory(), this)
context.lifecycle()?.addObserver(poolToUse)
pools.add(poolToUse)
}View on GitHub (pinned to e45bd3a61f)