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

  1. Ensure pixelDistance is always Math.abs(delta) or a non-negative computed value.
  2. Skip addPosition when the candidate is already inside the viewport (distance <= 0).
  3. 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

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


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/3337fd367efa3e71. Report an issue: GitHub.