{"record":{"id":"171dac4768fa18e5","repo":"marmelab/react-admin","slug":"ra-navigation-page-out-of-boundaries","errorCode":null,"errorMessage":"ra.navigation.page_out_of_boundaries","messagePattern":"ra\\.navigation\\.page_out_of_boundaries","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ra-ui-materialui/src/list/pagination/Pagination.tsx","lineNumber":52,"sourceCode":"        setPerPage,\n    } = useListPaginationContext();\n    const translate = useTranslate();\n    const isSmall = useMediaQuery((theme: Theme) =>\n        theme.breakpoints.down('md')\n    );\n\n    const totalPages = useMemo(() => {\n        return total != null ? Math.ceil(total / perPage) : undefined;\n    }, [perPage, total]);\n\n    /**\n     * Warning: Material UI's page is 0-based\n     */\n    const handlePageChange = useCallback(\n        (event, page) => {\n            event && event.stopPropagation();\n            if (page < 0 || (totalPages && page > totalPages - 1)) {\n                throw new Error(\n                    translate('ra.navigation.page_out_of_boundaries', {\n                        page: page + 1,\n                    })\n                );\n            }\n            setPage(page + 1);\n        },\n        [totalPages, setPage, translate]\n    );\n\n    const handlePerPageChange = useCallback(\n        event => {\n            setPerPage(event.target.value);\n        },\n        [setPerPage]\n    );\n\n    const labelDisplayedRows = useCallback(","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-ui-materialui/src/list/pagination/Pagination.tsx#L34-L70","documentation":"Pagination guards against out-of-range page changes from the MUI TablePagination input (page is 0-based internally; the message shows page+1). If the user somehow navigates to page < 0 or beyond the last page, react-admin throws a translated ra.navigation.page_out_of_boundaries error.","triggerScenarios":"Total/totalPages shrinking (e.g. after a filter or delete) while the current page number remains high, or manual page entry beyond the last page.","commonSituations":"Deleting all records on the last page, applying filters that reduce totalPages while page stays elevated, or custom pagination logic bypassing setPage bounds.","solutions":["Clamp the page passed to the list controller (setPage) within 0..totalPages-1.","Ensure totalPages/total are correctly supplied by the dataProvider (json-server style X-Total-Count).","Reset the page when filters change (List does this automatically; avoid overriding page outside useListContext)."],"exampleFix":"// before\nsetPage(newPage);\n// after\nconst safePage = Math.max(0, Math.min(newPage, (totalPages ?? newPage + 1) - 1));\nsetPage(safePage);","handlingStrategy":"try-catch","validationCode":"const inBounds = (page: number, totalPages?: number) => page >= 0 && (!totalPages || page <= totalPages - 1);\nif (!inBounds(page, totalPages)) setPage(Math.max(0, (totalPages ?? 1) - 1));","typeGuard":"const isValidPage = (p: unknown, totalPages?: number): p is number => typeof p === 'number' && Number.isInteger(p) && p >= 0 && (totalPages == null || p <= totalPages - 1);","tryCatchPattern":"error => { if (error.message === 'ra.navigation.page_out_of_boundaries' || error.message.includes('page_out_of_boundaries')) { setPage(1); return; } throw error; }","preventionTips":["Reset page to 1 whenever filters/sort change.","Keep total accurate in the dataProvider response.","Clamp user-entered page numbers before setPage."],"tags":["react-admin","pagination","out-of-range"],"backgroundTag":"page-out-of-bounds","analyzedSha":"051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0","analyzedAt":"2026-08-30T02:28:14.926Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}