Steps to reproduce
Live reproduction: https://github.com/tomups/mui-sx-theme-mutation-repro
git clone https://github.com/tomups/mui-sx-theme-mutation-repro
cd mui-sx-theme-mutation-repro
npm install
npm run dev
Steps:
- Open the app in a browser (resize to md+ breakpoint, ≥900px)
- Observe the
theme.typography.h4 dump at the bottom — it already contains width and marginTop properties that don't belong to it
- The plain
<Typography variant="h4"> above it picks up those stray properties
The triggering component is:
<Box sx={{ typography: { md: 'h4' }, width: { md: '80%' }, mt: { md: 4 } }}>
Current behavior
After the component renders, theme.typography.h4 is permanently mutated to include CSS properties from sibling sx keys that target the same breakpoint. For the example above, theme.typography.h4 ends up containing { ..., width: '80%', marginTop: '32px' }.
The corruption persists across renders and affects every component that uses variant="h4".
Expected behavior
theme.typography.h4 should not be modified. The sx prop should produce the correct CSS output without mutating the theme.
Context
We hit this upgrading a production app from MUI v7 to v9. Components that use sx={{ typography: { md: 'h4' }, ... }} alongside other responsive properties silently corrupt the theme, causing unrelated components to inherit stray CSS. The symptoms are confusing because they depend on render order and accumulate over time.
The root cause is in setThemeValue in @mui/system/styleFunctionSx/styleFunctionSx.js:
const themeMapping = getPath(theme, themeKey);
iterateBreakpoints(css, theme, value, (mediaKey, valueFinal) => {
const finalValue = getStyleValue2(themeMapping, transform, valueFinal, prop);
if (cssProperty === false) {
if (mediaKey) {
css[mediaKey] = finalValue; // assigns theme object by reference
} else {
merge(css, finalValue); // non-responsive path correctly uses merge
}
}
});
getStyleValue2 resolves 'h4' to theme.typography.h4 by reference via getPath. The responsive branch then does css[mediaKey] = finalValue, which replaces the breakpoint's CSS accumulator with a direct reference to the live theme object. After that, any other responsive sx key targeting the same breakpoint writes into the theme:
// Processing width: { md: '80%' } for the same breakpoint:
css[mediaKey][cssProperty] = finalValue;
// css[mediaKey] IS theme.typography.h4, so this mutates the theme
The non-responsive path uses merge(css, finalValue) which copies properties without creating a reference. The responsive path should do the same.
This was introduced by #44254.
Your environment
npx @mui/envinfo
System:
OS: Linux 6.6 Ubuntu 24.04.4 LTS
Binaries:
Node: 24.10.0
npm: 11.6.1
Browsers:
Chrome: 146.0.7680.75
npmPackages:
@emotion/react: ^11.14.0 => 11.14.0
@emotion/styled: ^11.14.1 => 11.14.1
@mui/material: ^9.0.0 => 9.0.0
@mui/system: 9.0.0
@types/react: ^19.0.0 => 19.2.14
react: ^19.0.0 => 19.2.5
react-dom: ^19.0.0 => 19.2.5
typescript: ^5.6.0 => 5.9.3
Search keywords: theme mutation typography sx responsive breakpoint corruption styleFunctionSx
Steps to reproduce
Live reproduction: https://github.com/tomups/mui-sx-theme-mutation-repro
git clone https://github.com/tomups/mui-sx-theme-mutation-repro cd mui-sx-theme-mutation-repro npm install npm run devSteps:
theme.typography.h4dump at the bottom — it already containswidthandmarginTopproperties that don't belong to it<Typography variant="h4">above it picks up those stray propertiesThe triggering component is:
Current behavior
After the component renders,
theme.typography.h4is permanently mutated to include CSS properties from sibling sx keys that target the same breakpoint. For the example above,theme.typography.h4ends up containing{ ..., width: '80%', marginTop: '32px' }.The corruption persists across renders and affects every component that uses
variant="h4".Expected behavior
theme.typography.h4should not be modified. The sx prop should produce the correct CSS output without mutating the theme.Context
We hit this upgrading a production app from MUI v7 to v9. Components that use
sx={{ typography: { md: 'h4' }, ... }}alongside other responsive properties silently corrupt the theme, causing unrelated components to inherit stray CSS. The symptoms are confusing because they depend on render order and accumulate over time.The root cause is in
setThemeValuein@mui/system/styleFunctionSx/styleFunctionSx.js:getStyleValue2resolves'h4'totheme.typography.h4by reference viagetPath. The responsive branch then doescss[mediaKey] = finalValue, which replaces the breakpoint's CSS accumulator with a direct reference to the live theme object. After that, any other responsive sx key targeting the same breakpoint writes into the theme:The non-responsive path uses
merge(css, finalValue)which copies properties without creating a reference. The responsive path should do the same.This was introduced by #44254.
Your environment
npx @mui/envinfoSearch keywords: theme mutation typography sx responsive breakpoint corruption styleFunctionSx