marmelab/react-admin · error · Error

ra.navigation.page_out_of_boundaries

Error message

ra.navigation.page_out_of_boundaries

What it means

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.

Source

Thrown at packages/ra-ui-materialui/src/list/pagination/Pagination.tsx:52

        setPerPage,
    } = useListPaginationContext();
    const translate = useTranslate();
    const isSmall = useMediaQuery((theme: Theme) =>
        theme.breakpoints.down('md')
    );

    const totalPages = useMemo(() => {
        return total != null ? Math.ceil(total / perPage) : undefined;
    }, [perPage, total]);

    /**
     * Warning: Material UI's page is 0-based
     */
    const handlePageChange = useCallback(
        (event, page) => {
            event && event.stopPropagation();
            if (page < 0 || (totalPages && page > totalPages - 1)) {
                throw new Error(
                    translate('ra.navigation.page_out_of_boundaries', {
                        page: page + 1,
                    })
                );
            }
            setPage(page + 1);
        },
        [totalPages, setPage, translate]
    );

    const handlePerPageChange = useCallback(
        event => {
            setPerPage(event.target.value);
        },
        [setPerPage]
    );

    const labelDisplayedRows = useCallback(

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Clamp the page passed to the list controller (setPage) within 0..totalPages-1.
  2. Ensure totalPages/total are correctly supplied by the dataProvider (json-server style X-Total-Count).
  3. Reset the page when filters change (List does this automatically; avoid overriding page outside useListContext).

Example fix

// before
setPage(newPage);
// after
const safePage = Math.max(0, Math.min(newPage, (totalPages ?? newPage + 1) - 1));
setPage(safePage);
Defensive patterns

Strategy: try-catch

Validate before calling

const inBounds = (page: number, totalPages?: number) => page >= 0 && (!totalPages || page <= totalPages - 1);
if (!inBounds(page, totalPages)) setPage(Math.max(0, (totalPages ?? 1) - 1));

Type guard

const isValidPage = (p: unknown, totalPages?: number): p is number => typeof p === 'number' && Number.isInteger(p) && p >= 0 && (totalPages == null || p <= totalPages - 1);

Try / catch

error => { if (error.message === 'ra.navigation.page_out_of_boundaries' || error.message.includes('page_out_of_boundaries')) { setPage(1); return; } throw error; }

Prevention

When it happens

Trigger: 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.

Common situations: Deleting all records on the last page, applying filters that reduce totalPages while page stays elevated, or custom pagination logic bypassing setPage bounds.

Related errors


AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30). Data as JSON: /api/errors/171dac4768fa18e5. Report an issue: GitHub.