{"record":{"id":"f7b04702c3a64e65","repo":"DrKLO/Telegram","slug":"index-out-of-bounds-passed-position-new-li","errorCode":null,"errorMessage":"Index out of bounds - passed position = {}, new list size = {}","messagePattern":"Index out of bounds - passed position = (.+?), new list size = (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"TMessagesProj/src/main/java/androidx/recyclerview/widget/DiffUtil.java","lineNumber":696,"sourceCode":"            } else {\n                return status >> FLAG_OFFSET;\n            }\n        }\n\n        /**\n         * Given a position in the new list, returns the position in the old list, or\n         * {@code NO_POSITION} if it was removed.\n         *\n         * @param newListPosition Position of item in new list\n         *\n         * @return Position of item in old list, or {@code NO_POSITION} if not present.\n         *\n         * @see #NO_POSITION\n         * @see #convertOldPositionToNew(int)\n         */\n        public int convertNewPositionToOld(@IntRange(from = 0) int newListPosition) {\n            if (newListPosition < 0 || newListPosition >= mNewListSize) {\n                throw new IndexOutOfBoundsException(\"Index out of bounds - passed position = \"\n                        + newListPosition + \", new list size = \" + mNewListSize);\n            }\n            final int status = mNewItemStatuses[newListPosition];\n            if ((status & FLAG_MASK) == 0) {\n                return NO_POSITION;\n            } else {\n                return status >> FLAG_OFFSET;\n            }\n        }\n\n        /**\n         * Finds a matching item that is before the given coordinates in the matrix\n         * (before : left and above).\n         *\n         * @param x The x position in the matrix (position in the old list)\n         * @param y The y position in the matrix (position in the new list)\n         * @param snakeIndex The current snake index\n         * @param removal True if we are looking for a removal, false otherwise","sourceCodeStart":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/src/main/java/androidx/recyclerview/widget/DiffUtil.java#L678-L714","documentation":"The mirror of error 9: convertNewPositionToOld maps a position in the NEW list back to the old list. mNewItemStatuses was sized to mNewListSize at DiffResult construction. Passing newListPosition outside [0, mNewListSize) is out of contract and would index out of bounds, so DiffUtil throws. This usually means the new list shrank or the caller is using a stale/newer list's position against an older DiffResult.","triggerScenarios":"Querying convertNewPositionToOld with a position from a later list version after the new list was replaced; using the old list size as the upper bound by mistake; the new list was mutated post-diff (same root cause as error 8).","commonSituations":"Stale DiffResult reused after submitList; position arithmetic mixing old/new indices; adapter that reuses DiffResult across refresh cycles.","solutions":["Use positions strictly within [0, new list size) as captured at DiffResult creation.","Recompute the diff on every data swap; never reuse a DiffResult after the backing list changes.","Bounds-check against the size recorded at diff time before converting."],"exampleFix":"// before\nint oldPos = result.convertNewPositionToOld(newPos); // may be stale\n\n// after\nint newSize = newList.size();\nint oldPos = (newPos >= 0 && newPos < newSize)\n    ? result.convertNewPositionToOld(newPos)\n    : DiffUtil.DiffResult.NO_POSITION;","handlingStrategy":"validation","validationCode":"// Bounds-check against the new list size captured at diff time\nint newSize = newSnap.size();\nint safeConvertOld(DiffUtil.DiffResult r, int newPos) {\n    if (newPos < 0 || newPos >= newSize) return DiffUtil.DiffResult.NO_POSITION;\n    return r.convertNewPositionToOld(newPos);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Track the new-list size at diff creation and clamp positions to it.","Discard stale DiffResults after submitList.","Avoid mixing old/new position indices in callbacks."],"tags":["recyclerview","diffutil","bounds","position-mapping"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}