marmelab/react-admin · warning
Failed to reuse custom theme from store
Error message
Failed to reuse custom theme from store
What it means
ThemeProvider wraps createTheme() in a try/catch when building the MUI theme from the lightTheme/darkTheme objects taken from the store. If the stored custom theme is invalid, createTheme throws and the library logs this warning instead of crashing, then falls back to the default Material UI theme. It means your custom theme object passed to <Admin theme={...}> could not be consumed by @mui/material's createTheme.
Source
Thrown at packages/ra-ui-materialui/src/theme/ThemeProvider.tsx:46
* </ThemeProvider>
* </ThemesContext.Provider>
* );
*/
export const ThemeProvider = ({ children }: ThemeProviderProps) => {
const { lightTheme, darkTheme, defaultTheme } = useThemesContext();
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)', {
noSsr: true,
});
const [mode] = useTheme(
defaultTheme || (prefersDarkMode && darkTheme ? 'dark' : 'light')
);
const themeValue = useMemo(() => {
try {
return createTheme(mode === 'dark' ? darkTheme : lightTheme);
} catch (e) {
console.warn('Failed to reuse custom theme from store', e);
return createTheme();
}
}, [mode, lightTheme, darkTheme]);
return (
<MuiThemeProvider theme={themeValue}>
{/* Had to cast here because Provider only accepts ReactNode but we might have a render function */}
{children as ReactNode}
</MuiThemeProvider>
);
};
export interface ThemeProviderProps {
children: AdminChildren;
}
View on GitHub (pinned to 051f511bb0)
Solutions
- Migrate the theme to the MUI v5 format: replace palette.type with palette.mode ('light'|'dark') and remove any options removed in MUI v5.
- Verify @mui/material resolves to a single version (npm ls @mui/material) and dedupe if multiple copies exist.
- Validate the theme by calling createTheme(myTheme) yourself in isolation; the thrown message identifies the offending key.
- Remove or minimize the theme object piece by piece (palette, components, typography) to find the invalid section.
- If no custom theme is needed, omit the theme prop so the default light/dark themes are used.
Example fix
// before (MUI v4 theme)
const theme = { palette: { type: 'dark', primary: { main: '#90caf9' } } };
<Admin theme={theme} ...>
// after (MUI v5 theme)
const theme = { palette: { mode: 'dark', primary: { main: '#90caf9' } } };
<Admin theme={theme} ...> Defensive patterns
Strategy: fallback
Validate before calling
import { createTheme } from '@mui/material/styles';
try {
createTheme(myTheme);
} catch (e) {
console.error('Invalid theme, fix before passing to <Admin>:', e);
} Type guard
const isPlainThemeObject = (t: unknown): t is Record<string, unknown> => typeof t === 'object' && t !== null && !Array.isArray(t) && !(typeof t === 'function');
Try / catch
let theme;
try {
theme = createTheme(customTheme);
} catch (e) {
console.warn('Falling back to default theme', e);
theme = createTheme();
} Prevention
- Always build themes with createTheme() from @mui/material/styles instead of hand-rolled plain objects.
- Keep @mui/material and @emotion deps on a single version across the app (check npm ls).
- When migrating react-admin versions, run the MUI codemods / migration guide for palette.type -> palette.mode.
- Test theme rendering in dev with console warnings visible before shipping.
When it happens
Trigger: Passing a theme object to <Admin theme={...}> (stored via react-admin's store) whose shape breaks createTheme: e.g. a v4 MUI theme (with old palette fields like type: 'dark') used with MUI v5, a theme built by a mismatched @mui/material version, a theme containing invalid palette/typography/shape values (wrong types, invalid tone numbers, malformed components overrides), or a null/undefined value where an object is expected in the overrides.
Common situations: Upgrading react-admin from v4 to v5 without migrating the theme from MUI v4 (palette.type -> palette.mode); mixing @mui/material versions via duplicate node_modules; hand-editing a theme and introducing a typo or wrong type; importing a theme from a tutorial built for an older MUI release.
Related errors
- useCanAccess must be used inside a <Resource> component or p
- useCreateController requires a non-empty resource prop or co
- useEditController requires a non-empty resource prop or cont
- useEditController requires an id prop or a route with an /:i
- useEditController: Fetched record's id attribute (${record.i
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/709d2cc5ee79b083.
Report an issue: GitHub.