marmelab/react-admin · info

No element with id "main-content" was found. Ensure the elem

Error message

No element with id "main-content" was found. Ensure the element that contains your main content has an id of "main-content".

What it means

SkipNavigationButton's skipToContent handler looks up the element with id "main-content" to move focus past the navigation. In non-production builds, if no such element exists it warns that the app layout is missing the required anchor, and the skip action does nothing.

Source

Thrown at packages/ra-ui-materialui/src/button/SkipNavigationButton.tsx:67

        opacity: 0.8,
        backgroundColor: (theme.vars || theme).palette.background.default,
    },
    '&:focus': {
        top: theme.spacing(2),
        transition: theme.transitions.create(['top', 'opacity'], {
            easing: theme.transitions.easing.easeOut,
            duration: theme.transitions.duration.enteringScreen,
        }),
    },
}));

const skipToContent = () => {
    if (typeof document === 'undefined') return;
    const element = document.getElementById('main-content');

    if (!element) {
        if (process.env.NODE_ENV !== 'production') {
            console.warn(
                'No element with id "main-content" was found. Ensure the element that contains your main content has an id of "main-content".'
            );
        }

        return;
    }

    element.setAttribute('tabIndex', '-1');
    element.focus();
    element.blur();
    element.removeAttribute('tabIndex');
};

declare module '@mui/material/styles' {
    interface ComponentNameToClassKey {
        RaSkipNavigationButton: 'root';
    }

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Give the element wrapping the layout children id="main-content" in your custom Layout.
  2. Use react-admin's default Layout, which already includes the main-content wrapper.
  3. In tests, mock skipToContent or render a stub element with id="main-content".

Example fix

// before (custom Layout)
<div className={classes.root}>
  <Menu />
  {children}
</div>
// after
<div className={classes.root}>
  <Menu />
  <div id="main-content">{children}</div>
</div>
Defensive patterns

Strategy: validation

Validate before calling

if (typeof document !== 'undefined' && !document.getElementById('main-content')) {
  console.warn('Custom Layout is missing <div id="main-content">');
}

Type guard

const hasMainContent = () => typeof document !== 'undefined' && document.getElementById('main-content') !== null;

Prevention

When it happens

Trigger: Clicking/activating the SkipNavigationButton (or calling skipToContent) in a custom Layout that lacks <div id="main-content"> around the children, or in tests rendering Layout fragments without the id.

Common situations: Building a custom Layout component without copying the main-content wrapper; upgrading Layout code and dropping the id; unit tests that render the button in isolation.


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