DrKLO/Telegram · error · IllegalArgumentException
Item at position {} requires {} spans but GridLayoutManager
Error message
Item at position {} requires {} spans but GridLayoutManager has only {} spans. What it means
GridLayoutManager assigns each item a span size via SpanSizeLookup.getSpanSize (default 1). During fill, it walks positions until the row/column span budget (mSpanCount) is consumed. If a single item's spanSize exceeds the total mSpanCount, the item can never fit in any row, so the layout is mathematically impossible and GridLayoutManager throws rather than entering an infinite loop or mis-rendering. The classic case is a 'full-width' header item with spanSize = spanCount while the grid was configured with a smaller spanCount than the lookup expects.
Source
Thrown at TMessagesProj/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java:541
// where they may have a header row which should be laid out according to children.
if (flexibleInOtherDir) {
updateMeasurements(); // reset measurements
}
final boolean layingOutInPrimaryDirection =
layoutState.mItemDirection == LayoutState.ITEM_DIRECTION_TAIL;
int count = 0;
int consumedSpanCount = 0;
int remainingSpan = mSpanCount;
if (!layingOutInPrimaryDirection) {
int itemSpanIndex = getSpanIndex(recycler, state, layoutState.mCurrentPosition);
int itemSpanSize = getSpanSize(recycler, state, layoutState.mCurrentPosition);
remainingSpan = itemSpanIndex + itemSpanSize;
}
while (count < mSpanCount && layoutState.hasMore(state) && remainingSpan > 0) {
int pos = layoutState.mCurrentPosition;
final int spanSize = getSpanSize(recycler, state, pos);
if (spanSize > mSpanCount) {
throw new IllegalArgumentException("Item at position " + pos + " requires "
+ spanSize + " spans but GridLayoutManager has only " + mSpanCount
+ " spans.");
}
remainingSpan -= spanSize;
if (remainingSpan < 0) {
break; // item did not fit into this row or column
}
View view = layoutState.next(recycler);
if (view == null) {
break;
}
consumedSpanCount += spanSize;
mSet[count] = view;
count++;
}
if (count == 0) {
result.mFinished = true;View on GitHub (pinned to 45ab8f4308)
Solutions
- Make SpanSizeLookup.getSpanSize return values bounded by the current GridLayoutManager.getSpanCount(), e.g. return getSpanCount() for full-width items.
- When changing spanCount at runtime, ensure the SpanSizeLookup logic scales with it.
- Use a header SpanSizeLookup that returns spanCount (the dynamic total), not a hardcoded number.
Example fix
// before
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override public int getSpanSize(int position) {
return isHeader(position) ? 4 : 1; // throws if spanCount < 4
}
});
// after
final GridLayoutManager glm = ...;
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override public int getSpanSize(int position) {
return isHeader(position) ? glm.getSpanCount() : 1;
}
}); Defensive patterns
Strategy: validation
Validate before calling
// Bound span size to the current span count
final GridLayoutManager glm = ...;
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override public int getSpanSize(int position) {
if (isHeader(position)) return glm.getSpanCount(); // dynamic
int s = itemSpanSize(position);
return Math.min(Math.max(1, s), glm.getSpanCount());
}
}); Prevention
- Return glm.getSpanCount() for full-width items, not a hardcoded number.
- Re-evaluate span sizes whenever spanCount changes (rotation, tablet).
- Clamp any external span size to [1, spanCount].
When it happens
Trigger: A SpanSizeLookup that returns spanCount for headers but the GridLayoutManager was created with a smaller spanCount (e.g. 3 vs lookup assuming 4); dynamic span count change (rotation, tablet) without recomputing span sizes; a lookup returning a hardcoded number larger than the configured span count.
Common situations: Mixed-item feeds (headers + grid items) where the header span size was hardcoded; rotation changing spanCount from 3 to 2 but SpanSizeLookup still returns 3; tablet/master-detail where span count varies but span sizes do not.
Related errors
- GridLayoutManager does not support stack from end. Consider
- Span count should be at least 1. Provided {}
- should not dispatch add or move for pre layout
- Invalid orientation. It should be either HORIZONTAL or VERTI
- {positionDescription}: Could not instantiate the LayoutManag
AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14).
Data as JSON: /api/errors/065e83e512d3bb21.
Report an issue: GitHub.