airbnb/epoxy · error · IllegalStateException
No view exists at position $position
Error message
No view exists at position $position
What it means
When resetting a ViewStub, removeCurrentView first removes whatever inflated view currently occupies the stub's position in the parent ViewGroup. If getChildAt(position) returns null, the position holds no view, so resetStub cannot proceed and throws this IllegalStateException rather than silently corrupting view ordering.
Solutions
- Only call resetStub for stub positions that currently hold an inflated view; check viewGroup.childCount first.
- Ensure the ViewGroup contents are managed exclusively by ModelGroupHolder — no external add/removeView calls.
- Rebind the group instead of resetting an already-cleared stub slot.
- If the view was removed elsewhere, re-add it via the normal bind path rather than resetStub.
Example fix
// before
holder.resetStub(position) // throws if no view at position
// after
if (position < viewGroup.childCount && viewGroup.getChildAt(position) != null) {
holder.resetStub(position)
} Defensive patterns
Strategy: validation
Validate before calling
fun canResetStub(parent: ViewGroup, position: Int) = position in 0 until parent.childCount && parent.getChildAt(position) != null
Prevention
- Do not add/remove children of the group's ViewGroup outside ModelGroupHolder.
- Reset stubs only between bind cycles, not after views were recycled away.
- Prefer a full rebind over targeted resetStub when state is uncertain.
When it happens
Trigger: Calling resetStub on a stub slot after the inflated view was already removed or never inflated; position drift caused by views being added/removed from the parent ViewGroup out of band.
Common situations: Rebinding a model group where a stub was reset earlier and its view recycled away; external code removing child views from the group's container; calling resetStub before the stub was inflated.
Related errors
- No view stubs found. If viewgroup is not empty it must…
- You must enable diffing before notifying models changed
- Model is not added
- Model is not added
- Model is not added
AI-assisted analysis of airbnb/epoxy@e45bd3a61f (2026-09-13).
Data as JSON: /api/errors/07fb0262af24a3f5.
Report an issue: GitHub.
Appendix: source
Thrown at epoxy-adapter/src/main/java/com/airbnb/epoxy/ModelGroupHolder.kt:238
if (inflatedId != View.NO_ID) {
view.id = inflatedId
}
if (useStubLayoutParams) {
viewGroup.addView(view, position, viewStub.layoutParams)
} else {
viewGroup.addView(view, position)
}
}
fun resetStub() {
removeCurrentView()
viewGroup.addView(viewStub, position)
}
private fun removeCurrentView() {
val view = viewGroup.getChildAt(position)
?: throw IllegalStateException("No view exists at position $position")
viewGroup.removeView(view)
}
}
/**
* Local pool to the [ModelGroupHolder]
*/
private class LocalGroupRecycledViewPool : RecyclerView.RecycledViewPool()
/**
* A viewholder's viewtype can only be set internally in an adapter when the viewholder
* is created. To work around that we do the creation in an adapter.
*/
private class HelperAdapter : RecyclerView.Adapter<EpoxyViewHolder>() {
private var model: EpoxyModel<*>? = null
private var modelGroupParent: ViewParent? = null
View on GitHub (pinned to e45bd3a61f)