DrKLO/Telegram · error · IllegalArgumentException
Pixel distance must be non-negative
Error message
Pixel distance must be non-negative
What it means
The companion guard in the same addPosition method as error 15. pixelDistance represents how far (in pixels) a candidate prefetch position is from the viewport edge; it drives prefetch priority ordering. A negative distance is nonsensical (cannot be 'closer than touching') and would corrupt the priority heap, so it is rejected. Like error 15, this fires from LayoutManager prefetch code that miscalculated distance — typically subtracting scroll offsets that underflow when the item is already fully visible.
Source
Thrown at TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java:120
}
}
if (mCount > layout.mPrefetchMaxCountObserved) {
layout.mPrefetchMaxCountObserved = mCount;
layout.mPrefetchMaxObservedInInitialPrefetch = nested;
view.mRecycler.updateViewCacheSize();
}
}
}
@Override
public void addPosition(int layoutPosition, int pixelDistance) {
if (layoutPosition < 0) {
throw new IllegalArgumentException("Layout positions must be non-negative");
}
if (pixelDistance < 0) {
throw new IllegalArgumentException("Pixel distance must be non-negative");
}
// allocate or expand array as needed, doubling when needed
final int storagePosition = mCount * 2;
if (mPrefetchArray == null) {
mPrefetchArray = new int[4];
Arrays.fill(mPrefetchArray, -1);
} else if (storagePosition >= mPrefetchArray.length) {
final int[] oldArray = mPrefetchArray;
mPrefetchArray = new int[storagePosition * 2];
System.arraycopy(oldArray, 0, mPrefetchArray, 0, oldArray.length);
}
// add position
mPrefetchArray[storagePosition] = layoutPosition;
mPrefetchArray[storagePosition + 1] = pixelDistance;
mCount++;View on GitHub (pinned to 45ab8f4308)
Solutions
- Ensure pixelDistance is always Math.abs(delta) or a non-negative computed value.
- Skip addPosition when the candidate is already inside the viewport (distance <= 0).
- Verify the LayoutManager passes the distance as the absolute pixel gap to the nearest viewport edge.
Example fix
// before
int dist = childTop - viewportBottom; // negative if child already visible
prefetchRegistry.addPosition(pos, dist);
// after
int dist = Math.max(0, childTop - viewportBottom);
if (dist > 0) {
prefetchRegistry.addPosition(pos, dist);
} Defensive patterns
Strategy: validation
Validate before calling
// Clamp pixel distance to non-negative
void safeAddPosition(LayoutPrefetchRegistry reg, int pos, int dist) {
int d = Math.max(0, dist);
if (pos >= 0 && d > 0) reg.addPosition(pos, d);
} Prevention
- Pass absolute pixel gap (Math.abs(delta)) as distance, never a signed delta.
- Skip addPosition for items already inside the viewport.
- Compute distance as the gap to the nearest viewport edge.
When it happens
Trigger: Custom LayoutManager.collectAdjacentPrefetchPositions computing distance as (edge - scrollOffset) when scrollOffset > edge; passing a raw scroll delta that is negative because the user scrolled in the opposite direction; a nested prefetch hook that does not abs() the direction-aware delta.
Common situations: Bidirectional scrolling LayoutManager where the distance sign is direction-dependent; custom snap helpers feeding prefetch; a fork that modified GapWorker distance accounting.
Related errors
- Layout positions must be non-negative
- view is not a child, cannot hide {}
- invalid orientation:{}
- invalid orientation
- {positionDescription}: Error creating LayoutManager {classNa
AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14).
Data as JSON: /api/errors/3337fd367efa3e71.
Report an issue: GitHub.