{"record":{"id":"3337fd367efa3e71","repo":"DrKLO/Telegram","slug":"pixel-distance-must-be-non-negative","errorCode":null,"errorMessage":"Pixel distance must be non-negative","messagePattern":"Pixel distance must be non-negative","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java","lineNumber":120,"sourceCode":"                    }\n                }\n\n                if (mCount > layout.mPrefetchMaxCountObserved) {\n                    layout.mPrefetchMaxCountObserved = mCount;\n                    layout.mPrefetchMaxObservedInInitialPrefetch = nested;\n                    view.mRecycler.updateViewCacheSize();\n                }\n            }\n        }\n\n        @Override\n        public void addPosition(int layoutPosition, int pixelDistance) {\n            if (layoutPosition < 0) {\n                throw new IllegalArgumentException(\"Layout positions must be non-negative\");\n            }\n\n            if (pixelDistance < 0) {\n                throw new IllegalArgumentException(\"Pixel distance must be non-negative\");\n            }\n\n            // allocate or expand array as needed, doubling when needed\n            final int storagePosition = mCount * 2;\n            if (mPrefetchArray == null) {\n                mPrefetchArray = new int[4];\n                Arrays.fill(mPrefetchArray, -1);\n            } else if (storagePosition >= mPrefetchArray.length) {\n                final int[] oldArray = mPrefetchArray;\n                mPrefetchArray = new int[storagePosition * 2];\n                System.arraycopy(oldArray, 0, mPrefetchArray, 0, oldArray.length);\n            }\n\n            // add position\n            mPrefetchArray[storagePosition] = layoutPosition;\n            mPrefetchArray[storagePosition + 1] = pixelDistance;\n\n            mCount++;","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java#L102-L138","documentation":"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.","triggerScenarios":"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.","commonSituations":"Bidirectional scrolling LayoutManager where the distance sign is direction-dependent; custom snap helpers feeding prefetch; a fork that modified GapWorker distance accounting.","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."],"exampleFix":"// before\nint dist = childTop - viewportBottom; // negative if child already visible\nprefetchRegistry.addPosition(pos, dist);\n\n// after\nint dist = Math.max(0, childTop - viewportBottom);\nif (dist > 0) {\n    prefetchRegistry.addPosition(pos, dist);\n}","handlingStrategy":"validation","validationCode":"// Clamp pixel distance to non-negative\nvoid safeAddPosition(LayoutPrefetchRegistry reg, int pos, int dist) {\n    int d = Math.max(0, dist);\n    if (pos >= 0 && d > 0) reg.addPosition(pos, d);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["recyclerview","gapworker","prefetch","distance","layoutmanager"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}