emotion
emotion copied to clipboard
Hydration error using Next.js 15 and MUI 6 when using Turbopack builder
Current behavior:
Using Next.js 15 and MUI 6, an Emotion-related hydration error appears when the page is SSR-rendered. After reading https://github.com/chakra-ui/chakra-ui/issues/8970, I figured out, this only happens using the new --turbopack builder from Next.js (which has been the new default for some time)
To reproduce:
- Clone https://github.com/kangalio/emotion-hydration-error-reproducible
- Run
npm installand thennpx next dev --turbopack - Open the website (i.e.
localhost:3000) - Observe:
Expected behavior:
I expect no error to be thrown.
Environment information:
@emotion/babel-plugin: 11.13.5@emotion/cache: 11.14.0@emotion/hash: 0.9.2@emotion/is-prop-valid: 1.3.1@emotion/memoize: 0.9.0@emotion/react: 11.14.0@emotion/serialize: 1.3.3@emotion/sheet: 1.4.0@emotion/styled: 11.14.0@emotion/unitless: 0.10.0@emotion/use-insertion-effect-with-fallbacks: 1.2.0@emotion/utils: 1.4.2@emotion/weak-memoize: 0.4.0react: 19.0.0react-dom: 19.0.0react-is: 16.13.1react-transition-group: 4.4.5
(Taken from the linked reproducible repo's package-lock.json)
Potentially related issues:
- https://github.com/emotion-js/emotion/issues/3222
I have the same issue when running with --turbopack:
Unhandled Runtime Error
Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used
- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.
It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
...
<OuterLayoutRouter parallelRouterKey="children" segmentPath={[...]} template={<RenderFromTemplateContext>}>
<RenderFromTemplateContext>
<ScrollAndFocusHandler segmentPath={[...]}>
<InnerScrollAndFocusHandler segmentPath={[...]} focusAndScrollRef={{apply:false, ...}}>
<ErrorBoundary errorComponent={undefined} errorStyles={undefined} errorScripts={undefined}>
<LoadingBoundary loading={null}>
<HTTPAccessFallbackBoundary notFound={undefined} forbidden={undefined} unauthorized={undefined}>
<RedirectBoundary>
<RedirectErrorBoundary router={{...}}>
<InnerLayoutRouter parallelRouterKey="children" url="/dashboard..." tree={[...]} childNodes={Map} ...>
<script>
<script>
<script>
<script>
<script>
<Layout>
<Box sx={{display:"flex"}}>
<Styled(div) as="div" ref={null} className="MuiBox-root" theme={{...}} sx={{display:"flex"}}>
<Insertion>
+ <div className="MuiBox-root css-k008qs">
- <style data-emotion="css-global ghzezc" data-s="">
I am also seeing this error with:
"@emotion/react": "11.14.0", "@emotion/styled": "11.14.0", "@heroicons/react": "2.2.0", "@mui/icons-material": "6.4.2", "@mui/material": "6.4.2",
Greetings!
I have the same problem, but with a slightly different configuration (NextJS 15 / Chakra UI 3)...what I have not done - nothing helps, but without --turbopack - the error disappears(
I am also having the same issue!
"@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^6.4.6", "@mui/material": "^6.1.10", "next": "15.1.0", "next-auth": "^4.24.11", "react": "^19.0.0", "react-dom": "^19.0.0",
node version 23.5.0
I was seeing this error too, and solved it.
First, error reproduction steps (skip several by cloning this at the linked-to point in history):
npx create-next app (installed v15.2.2, the latest)
Project name: emotion3308
TypeScript, ESLint, Tailwind, src/ dir, app router, Turbopack: Yes
Customize import alias: No
cd emotion3308
npm i @mui/material @emotion/react @emotion/styled
In src/app/page.tsx, add import Button from '@mui/material/Button';
In the same file just before the first <Image add:
{/* You can get rid of both the error (and the button) by moving the contents of
the next line to the end of the line below it.
*/}
<Button>Problem Causer</Button>
Or you can skip all that and just clone this at the linked-to point in the commit history.
Then npm run dev (aka next dev --turbopack) and the issue is observed. Note that if you make changes and rely on the soft reload, ANY change you make will appear to fix the issue. Be sure to do an F5 full page reload to test and see if you see the error.
I found this issue from last summer in which <Typography> was being rendered as <span> on the server and <p> on the client which leads to a mismatch. However, in that case, updating to the latest canary version of Next worked, and that has since been released but the problem is still being observed. I also found this still-open issue from around the same time frame. Per this comment, wrapping with an MUI <Box> fixes the issue, but that does not seem like an ideal solution.
Per this older Reddit post, following the MUI instructions for Next.js integration did much better. Namely, stop the server, npm i @mui/material-nextjs @emotion/cache (the latter just makes the dependency more explicit), then modify src/app/layout.tsx to import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter'; at the top and wrap the {props.children} line in <AppRouterCacheProvider>β¦ </AppRouterCacheProvider>. There are some other useful instructions there. I would propose closing this Issue.
Also happens with MUI 7, and only with turbopack.
@lucach Are you following the MUI instructions for Next.js integration?
@lucach Are you following the MUI instructions for Next.js integration?
I am.
I'm already using the *CacheProvider wrapper component. I'm still using the Pages router, so the wrapper is AppCacheProvider, from @mui/material-nextjs/v15-pagesRouter.
@lucach Are you following the MUI instructions for Next.js integration?
I am.
I'm already using the
*CacheProviderwrapper component. I'm still using the Pages router, so the wrapper isAppCacheProvider, from@mui/material-nextjs/v15-pagesRouter.
To be more precise: the page renders correctly. The hydration error is only shown in the console. Classes only differ by their prefix:
<div
+ className="MuiBox-root mui-wao269"
- className="MuiBox-root css-wao269"
>
@lucach Are you following the MUI instructions for Next.js integration?
This fixed it for me π
It does work but not in the turbopack mode. Are you seeing this error when running next --turbopack?
@barthicus No, the problem is in normal mode without turbopack. As @lucach pointed out, the project is on Pages router.
I have the same problem.
We have the same problem using the Pages router, with or without turbopack. The problem does not occur if using the App router.
I'm using the App router and the problem occurs with turbopack.
On Mon, May 19, 2025, 03:41 JB-Scott @.***> wrote:
JB-Scott left a comment (emotion-js/emotion#3308) https://github.com/emotion-js/emotion/issues/3308#issuecomment-2889296880
We have the same problem using the Pages router, with or without turbopack. The problem does not occur if using the App router.
β Reply to this email directly, view it on GitHub https://github.com/emotion-js/emotion/issues/3308#issuecomment-2889296880, or unsubscribe https://github.com/notifications/unsubscribe-auth/AL3VALBB6EMHENJBAQ4XG4T27EOUHAVCNFSM6AAAAABVWBT26WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQOBZGI4TMOBYGA . You are receiving this because you commented.Message ID: @.***>
I'm using the App router and the problem occurs with turbopack.
@smartdeveler Are you following the MUI instructions for Next.js integration? That fixed it for me using the app router with turbopack.
Yes. I following that instruction but not fixed with turbopack.
We are also seeing similar issues. Any guidance so far from MUI team?
I updated some of our dependencies, now we are using mui/material 7.2.0 and @emotion/styled 11.14.1 and it seems to solve the issue. I did a POC with this dependencies and it worked fine for me:
"@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", "next": "15.3.5", "react": "^19.0.0", "react-dom": "^19.0.0"
Im using App Router with turbopack.
Hope it helps somebody someday.
I updated some of our dependencies, now we are using mui/material 7.2.0 and @emotion/styled 11.14.1 and it seems to solve the issue. I did a POC with this dependencies and it worked fine for me:
"@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@mui/icons-material": "^7.2.0", "@mui/material": "^7.2.0", "next": "15.3.5", "react": "^19.0.0", "react-dom": "^19.0.0"
Im using App Router with turbopack.
Hope it helps somebody someday.
This worked for me with update : "@mui/icons-material": "^7.2.0", "next": "15.3.5",
Same error with ChakraUI, Next, and Turbopack:
<RootLayout>
<html lang="en" suppressHydrationWarning={true}>
<body className="geist_a715...">
<Provider>
<ChakraProvider value={{$$chakra:true, ...}}>
<EmotionGlobal>
<EmotionGlobal>
<ColorModeProvider>
<J attribute="class" disableTransitionOnChange={true}>
<V attribute="class" disableTransitionOnChange={true}>
+ <script
+ suppressHydrationWarning={true}
+ nonce=""
+ dangerouslySetInnerHTML={{__html:"((e, i, s,..."}}
+ >
- <style data-emotion="css-global ad1llf" data-s="">
In my case I got such errors because I'm using MaterialUI and I was using StyledEngineProvider (@mui/material) as a child of AppRouterCacheProvider (@mui/material-nextjs/v13-appRouter). Making StyledEngineProvider a parent of AppRouterCacheProvider solved most errors about different css.
The remaining css hydration issues was because I was using emotion CacheProvider (@emotion/react, along with createCache from @emotion/cache) and somehow it was conflicting with MaterialUI cache, that probably uses the emotion provider under the hood, so I just removed the emotion CacheProvider and kept just AppRouterCacheProvider.
Confirmed: Issue persists with Next.js 15.5.4 + Turbopack
Environment:
- Next.js:
15.5.4 - Turbopack:
--turbopackflag - Emotion: Latest version
- App Router: Yes
Reproduction:
The hydration error only occurs when using --turbopack. Running the same code with the default webpack bundler works fine without any hydration warnings.
Current Workaround: For developers experiencing this issue, the only reliable workaround is to disable Turbopack during development:
# Instead of
npm run dev --turbopack
# Use
npm run dev
I was able to fix the issue by removing <StyledEngineProvider injectFirst>. When using <AppRouterCacheProvider>, you donβt need to wrap it manually because it already handles style injection automatically.
Details: In my app, <StyledEngineProvider> was nested inside <AppRouterCacheProvider>, which caused style injection conflicts and the insertBefore error. Removing it solved the problem.
For best results, make sure to follow the official MUI documentation:
If it still doesnβt work, you can try this workaround:
import { createCache } from "@emotion/react";
createCache({ key: "mui", prepend: true });
return (
<html>
<body>
<AppRouterCacheProvider>
<MuiThemeProvider theme={yourCurrentActiveTheme}>
<CssBaseline />
{children}
</MuiThemeProvider>
</AppRouterCacheProvider>
</body>
</html>
);
So at this point it seams that the problem has a solution for app router but not for pages router. I made this repro repo : https://github.com/Mattgic/next-mui-turbopack-bug with an example page on app router and another on pages router. I only have an error with pages router, and only if I run Next with Turbopack.
I also have no errors if I try to add custom emotion css (with css prop) on a div with pages router + Turbopack
On this repo I use Next v15 because @mui/material-nextjs is still not compatible with Next v16.
So the problem seems to be Turbopack + MUI + Pages router
I guess the problem is more on the Turbopack side than on MUI ?