material-ui: [material-ui] Not working after upgrading Next.js to 14.0.4. Error: Element type is invalid.

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Steps to reproduce 🕹

I created a sample repository here.

Steps:

  1. Create a new Next.js project: npx create-next-app@latest (select the app router and typescript),
  2. Install Material-UI: npm install @mui/material @emotion/react @emotion/styled @mui/material-nextjs @emotion/cache
  3. Wrap the children in the root layout with the AppRouterCacheProvider, as it is described here,
  4. Add any @mui/material component above the {children} in the Root layout (I added the <CSSBaseline /> but also tried with another Typography):
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AppRouterCacheProvider>
          <CssBaseline />
          {children}
        </AppRouterCacheProvider>
      </body>
    </html>
  );
}
  1. Add any @mui/material component to the app/page.tsx file. I tried Box and Typography.
import Image from "next/image";
import styles from "./page.module.css";
import { Box, Typography } from "@mui/material";

export default function Home() {
  return (
    <main className={styles.main}>
      <Typography>Hello!</Typography>
    </main>
  );
}
  1. Run the project: npm run dev
  2. You will see the following error:
image

Note: Somehow it works when I remove all @mui/material-ui components from the layout (CSSBaseline in the above example) - but it should be allowed and normal to have mui components in the root layout.

Current behavior 😯

The error:

Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.

Your environment 🌎

npx @mui/envinfo
System:
    OS: macOS 14.1.2
  Binaries:
    Node: 18.18.0 - ~/.nvm/versions/node/v18.18.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v18.18.0/bin/yarn
    npm: 10.2.5 - ~/Repos/material-ui-next-14-0-4/node_modules/.bin/npm
  Browsers:
    Chrome: 120.0.6099.109
    Edge: Not Found
    Safari: 17.1.2
  npmPackages:
    @emotion/react: ^11.11.1 => 11.11.1
    @mui/base:  5.0.0-beta.27
    @mui/core-downloads-tracker:  5.15.0
    @mui/material: ^5.15.0 => 5.15.0
    @mui/material-nextjs: ^5.15.0 => 5.15.0
    @mui/private-theming:  5.15.0
    @mui/styled-engine:  5.15.0
    @mui/system:  5.15.0
    @mui/types:  7.2.11
    @mui/utils:  5.15.0
    @types/react: ^18 => 18.2.45
    react: ^18 => 18.2.0
    react-dom: ^18 => 18.2.0
    typescript: ^5 => 5.3.3

About this issue

  • Original URL
  • State: closed
  • Created 7 months ago
  • Reactions: 35
  • Comments: 43 (3 by maintainers)

Most upvoted comments

I also encountered a problem.

“next”: “^14.0.4”, “@mui/material”: “^5.15.1”

For now, here’s what helped me get around the problem. Added /index.

Example: import { Box, Card } from '@mui/material/index'

Encountered this issue today. As @leonoheart mentioned, this is probably due to MUI dynamically importing certain styles or components.

I found that using the modularizeImports option, also unfortunately RESULTS in the same error.

const nextConfig = {
    modularizeImports: {
      "@mui/material": {
        transform: "@mui/material/{{member}}",
      },
  }
}

Workaround

This may be somewhat tedious, but the following works for a good deal of MUI components. The benefit, is that this maintains tree-shaking optimizations.

Change:

import {Container, Typography} from '@mui/material'

To:

import Container from "@mui/material/Container";
import Typography from "@mui/material/Typography";

If this can be done automatically, prior to the build or development step, without using next.js’s modularizeImports option, this could be automated for a large project.

Suggestions:
  1. Looking into the source code for the following library can yield some results (for large projects).

  2. Configuring babel with next js, and writing a ruleset to convert the imports. Look at an example here (unfortunately, only useful if you aren’t using app router)

@ceefour The previous one worked just fine for me - 14.0.3

Just writing to inform everyone that this issue has been fixed in the latest Next.js canary release v14.0.5-canary.62 .

It’s broken again with next@14.2.0

 [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.] 

This workaround fixed the problem for me:

Error

import { Button } from '@mui/material'

Unhandled Runtime Error Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.

Solution

import Button from '@mui/material/Button'

+1 Everything is working on 14.0.3, after upgrade to 14.0.4

Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.

I get this error too for SSR pages, from the components like Stack and Typography.

There is this issue https://github.com/vercel/next.js/issues/59804 that’s already been raised

Confirmed broke again on 14.2.1

Although this workaround fixes the errors in the client side, I just noticed some error logs after app starts, these errors happen in 14.0.4 only. I had to downgrade to Next 14.0.3 to avoid them.

npm run dev
Debugger attached.

> example@0.0.1 dev
> next dev

Debugger attached.
   ▲ Next.js 14.0.4
   - Local:        http://localhost:3000
   - Environments: .env

Waiting for the debugger to disconnect...
 ✓ Ready in 3.3s
 ○ Compiling /[alias] ...
 ✓ Compiled /[alias] in 4.1s (2007 modules)

⨯ Internal error: Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it’s defined in, or you might have mixed up default and named imports.

@dus4nstojanovic I encountered the same issue. Now I think i have fixed the issue by replacing all @mui/material with @mui/system when importing Box component from MUI and keep other import path from MUI as it is in my project(maybe Grid/Stack/Divider are the same with Box but i have not tested on them). It seems that Box from @mui/material dynamically import some style but @mui/system not.

import { Box } from '@mui/material'; 
↓
import { Box } from '@mui/system';

In my case, CssBaseline does not give an error. Any MUI component added to the layout file works fine. I have an AppBar there. What does not work is SSR pages. When I remove MUI components from the page, the page with the components in the layout is displayed.

I want this issue to be fixed really fast and I am ready to contribute. I cannot run the website without this fixed. It will take much longer to switch to another UI framework or library.

Using the official “MUI Next.js App Routerexample project with Nextjs 14.0.4 works just fine.

It appears to have a custom EmotionCache instead of the AppRouterCacheProvider, though they files are nearly identical so I don’t understand why EmotionCache works while AppRouterCacheProvider doesn’t.

Here are the changes made in Next14.0.4. There is a lot of stuff but we don’t encounter them very frequently. Be aware of those changes and try to switch to 14.0.3.

I do not recommend making something like layout a client component just to fix this issue. Plus if the project uses MUI then MUI components are used almost everywhere. So you will end up making every server side component a client component. Not a good way to leverage the benefits of NextJS. Changing import paths in a large project is nearly impossible. Plus this will be fixed soon. Then you will have to change them back to normal imports. If you are just starting a project, it will be fine.

I recently downgraded a considerably large project from 14.0.4 to 14.0.3. But still did not encounter an issue due to the downgrade. I recommend that way.

@leonoheart Thank you for a workaround.

But doing this in a big application, and checking every material-ui component is certainly not the solution. Plus, the material-ui recommends importing everything from @mui/material (including the Box component: link). I also believe having some components imported from @mui/material and some from @mui/system is not good for tree shaking, too.

Since the imports are in the game, possible the next.js automatic optimizePackageImports feature caused the problem. But this is only my guess.

Let’s see what the maintainer says.

I’m also getting this error

@mui/material”: “^5.15.0”, “next”: “^14.0.4”,

SSR pages no longer work “Error: Element type is invalid. Received a promise that resolves to: undefined. Lazy element type must resolve to a class or function.”

Had this issue today. My way to fix it in root layout JS is added new component like MainLayout and give him “use client” prop

"use` client";

import { CssBaseline } from "@mui/material";
import React, { PropsWithChildren } from "react";

export const MainLayout: React.FC<PropsWithChildren> = ({ children }) => (
  <React.Fragment>
    <CssBaseline />
    {children}
  </React.Fragment>
);

and dirrectly wrap all in root layout like this


import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter";
import { MainLayout } from "@/layouts/main";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "Next.JS - app",
  description:
    "Next.js app",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <AppRouterCacheProvider>
          <MainLayout>{children}</MainLayout>
        </AppRouterCacheProvider>
      </body>
    </html>
  );
}

@dus4nstojanovic Thanks, confirmed that it works with Nextjs 14.0.3 but crashed with 14.0.4 (SSR pages only).