{"record":{"id":"2458a6324c39daaa","repo":"DrKLO/Telegram","slug":"is-not-within-0-and","errorCode":null,"errorMessage":"{} is not within 0 and {}","messagePattern":"(.+?) is not within 0 and (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListUtil.java","lineNumber":156,"sourceCode":"     * Returns the data item at the given position or <code>null</code> if it has not been loaded\n     * yet.\n     *\n     * <p>\n     * If this method has been called for a specific position and returned <code>null</code>, then\n     * {@link ViewCallback#onItemLoaded(int)} will be called when it finally loads. Note that if\n     * this position stays outside of the cached item range (as defined by\n     * {@link ViewCallback#extendRangeInto} method), then the callback will never be called for\n     * this position.\n     *\n     * @param position Item position.\n     *\n     * @return The data item at the given position or <code>null</code> if it has not been loaded\n     *         yet.\n     */\n    @Nullable\n    public T getItem(int position) {\n        if (position < 0 || position >= mItemCount) {\n            throw new IndexOutOfBoundsException(position + \" is not within 0 and \" + mItemCount);\n        }\n        T item = mTileList.getItemAt(position);\n        if (item == null && !isRefreshPending()) {\n            mMissingPositions.put(position, 0);\n        }\n        return item;\n    }\n\n    /**\n     * Returns the number of items in the data set.\n     *\n     * <p>\n     * This is the number returned by a recent call to\n     * {@link DataCallback#refreshData()}.\n     *\n     * @return Number of items.\n     */\n    public int getItemCount() {","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/src/main/java/androidx/recyclerview/widget/AsyncListUtil.java#L138-L174","documentation":"AsyncListUtil lazily loads data items in background tiles and exposes getItem(position) to the UI thread. mItemCount is the total data set size reported by the DataCallback.refreshData contract. Requesting a position < 0 or >= mItemCount is out of contract because the underlying tile grid only covers [0, mItemCount). The exception is a hard bounds check — there is no valid item outside that range, so the call cannot return data and fails fast instead of returning a wrong value.","triggerScenarios":"The RecyclerView adapter getItemCount() returns a larger value than the AsyncListUtil mItemCount (size mismatch between adapter and the AsyncListUtil); a position derived from a stale cursor after the data set changed; off-by-one when mapping a scroll position to an item index.","commonSituations":"Calling refresh() on the AsyncListUtil without also updating the adapter count; the adapter and DataCallback disagree on total count after a background refresh; rapid scroll past the end during a data swap.","solutions":["Ensure RecyclerView.Adapter.getItemCount() and AsyncListUtil.DataCallback.refreshData report the same total count, and call asyncListUtil.refresh() whenever the count changes.","Guard the call site: if (position >= 0 && position < asyncListUtil.getItemCount()) before getItem.","Update the adapter's itemCount atomically with the AsyncListUtil refresh to avoid stale positions."],"exampleFix":"// before\nString item = asyncListUtil.getItem(position); // may throw if stale\n\n// after\nif (position >= 0 && position < asyncListUtil.getItemCount()) {\n    String item = asyncListUtil.getItem(position);\n} else {\n    item = null;\n}","handlingStrategy":"validation","validationCode":"// Bounds-check before getItem\npublic <T> T safeGet(AsyncListUtil<T> util, int position) {\n    if (position < 0 || position >= util.getItemCount()) return null;\n    return util.getItem(position);\n}","typeGuard":null,"tryCatchPattern":"try { return asyncListUtil.getItem(position); } catch (IndexOutOfBoundsException e) { Log.w(TAG, \"stale position \" + position); return null; }","preventionTips":["Keep adapter.getItemCount() in lockstep with asyncListUtil.refresh() calls.","Snapshot positions before async load completes.","Defensively bounds-check at the adapter.onBindViewHolder call site."],"tags":["recyclerview","asynclistutil","bounds","lazy-loading"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}