Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next 15: createTheme(): RangeError: Maximum call stack size exceeded #44278

Open
nphmuller opened this issue Oct 30, 2024 · 4 comments · May be fixed by #44400
Open

Next 15: createTheme(): RangeError: Maximum call stack size exceeded #44278

nphmuller opened this issue Oct 30, 2024 · 4 comments · May be fixed by #44400
Assignees
Labels
nextjs package: utils Specific to the @mui/utils package

Comments

@nphmuller
Copy link
Contributor

nphmuller commented Oct 30, 2024

Steps to reproduce

Link to live example: https://github.com/nphmuller/mui-next-15_0_2_issue

Steps:

  1. npx create-next-app@latest
  2. Add custom ThemeProvider with createTheme using another React component
    Example:
createTheme({
  components: {
    MuiCheckbox: {
      defaultProps: {
        // Comment this out and the error goes away
        icon: <InfoSharp />,
      },
    },
  },
});
  1. Add ThemeProvider in layout.tsx
  2. npm run dev
  3. Go to localhost:3000

Full ThemeProvider:

"use client";

import { ThemeProvider } from "@mui/material";
import { createTheme } from "@mui/material/styles";
import InfoSharp from "@mui/icons-material/InfoSharp";

createTheme({
  components: {
    MuiCheckbox: {
      defaultProps: {
        // Comment this out and the error goes away
        icon: <InfoSharp />,
      },
    },
  },
});

export default function Wrapper({ children }: { children: React.ReactNode }) {
  return <ThemeProvider theme={createTheme()}>{children}</ThemeProvider>;
}

Current behavior

Error in console:

 ⨯ RangeError: Maximum call stack size exceeded
    at isPlainObject (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:376:23)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:384:10)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
    at /Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:389:23
    at Array.forEach (<anonymous>)
    at deepClone (/Users/nphmuller/Dev/_tests/mui-next-15_0_2_issue/.next/server/chunks/ssr/node_modules_b945aa._.js:388:25)
digest: "3211407037"

Expected behavior

No error in console

Context

The issue occurs in deepmerge in @mui/utils. It doesn't handle looping references, which seems to happen in the latest Next version for React component in some cases.

I initially suspected this was a Next issue, but after investigating I think it's probably a MUI issue.

The main issue is that in recent versions of React and when using Next the internal _owner key of a React component can contain a value that is referencing itself. This causes an infinite loop in deepClone() which causes the error above.

See this PR for more info (vercel/next.js#71968), but basically the issue starts to occur after Next started using the registerClientReference function of React instead of createClientModuleProxy. This initially only happend for turbopack in Next 15, but in Next 15.0.2 webpack was aligned with turbopack and now both builds use registerClientReference, so the issue now always occurs when running next dev.

I opened this issue in Next a couple days ago when I thought it was mainly a Next issue. I haven't received a response there yet, but hopefully we'll hear soon what their conclusion is: vercel/next.js#71878

The repro there contains more lower level details about how the issue occurs, but this is the gist of it:

function deepClone<T>(source: T): T {
  if (!isPlainObject(source)) {
    return source;
  }

  const output: Record<any, any> = {};

  Object.keys(source).forEach((key) => {
    if (key === "_owner") {
      // !!!!! Here's the difference between webpack and turbopack !!!!!
      // !!!!! In webpack the value of _owner is null (until Next 15.0.2) !!!!!
      // !!!!! In turbopack the value of _owner is not null !!!!
      console.log("key " + key + " is null " + source[key] === null);
      console.log(source[key]);
    }
    output[key] = deepClone(source[key]);
  });

  return output;
}

// https://github.com/sindresorhus/is-plain-obj/blob/main/index.js
function isPlainObject(item: unknown): item is Record<keyof any, unknown> {
  if (typeof item !== "object" || item === null) {
    return false;
  }

  const prototype = Object.getPrototypeOf(item);

  const res =
    (prototype === null ||
      prototype === Object.prototype ||
      Object.getPrototypeOf(prototype) === null) &&
    !(Symbol.toStringTag in item) &&
    !(Symbol.iterator in item);

  return res;
}

Here's an example of the value of the _owner field (in older versions it was null):

{
  parent: {
    parent: { parent: [Object], type: 'html', owner: [Object], stack: null },
    type: 'body',
    owner: {
      name: 'RootLayout',
      env: 'Server',
      key: null,
      owner: null,
      props: [Object]
    },
    stack: null
  },
  type: {
    '$$typeof': Symbol(react.lazy),
    _payload: Promise {
      status: 'resolved_module',
      value: [Array],
      reason: null,
      _response: [ResponseInstance],
      _debugInfo: []
    },
    _init: [Function: readChunk],
    _debugInfo: []
  },
  owner: {
    name: 'RootLayout',
    env: 'Server',
    key: null,
    owner: null,
    props: { children: [Object], params: [Getter] }
  },
  stack: null
}

Your environment

npx @mui/envinfo
  System:
    OS: macOS 15.0
  Binaries:
    Node: 20.13.0 - ~/.nvm/versions/node/v20.13.0/bin/node
    npm: 10.9.0 - ~/.nvm/versions/node/v20.13.0/bin/npm
    pnpm: 9.6.0 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 130.0.6723.71
    Edge: Not Found
    Safari: 18.0
  npmPackages:
    @emotion/react: ^11.13.3 => 11.13.3
    @emotion/styled: ^11.13.0 => 11.13.0
    @mui/core-downloads-tracker:  6.1.6
    @mui/icons-material: ^6.1.5 => 6.1.6
    @mui/material: ^6.1.5 => 6.1.6
    @mui/private-theming:  6.1.6
    @mui/styled-engine:  6.1.6
    @mui/system:  6.1.6
    @mui/types:  7.2.19
    @mui/utils:  6.1.6
    @types/react: ^18 => 18.3.12
    react: 19.0.0-rc-69d4b800-20241021 => 19.0.0-rc-69d4b800-20241021
    react-dom: 19.0.0-rc-69d4b800-20241021 => 19.0.0-rc-69d4b800-20241021
    typescript: ^5 => 5.6.3

Search keywords: createTheme RangeError Next15 Next

@HasanMothaffar
Copy link

I'm facing the same issue. I'm using nextjs 15.0.2 and @mui/material 6.1.6. However, I'm getting the issue whether I'm using turbopack or not.

This is the block that causes the issue:

const themeConfig = {
    components: {
         MuiCheckbox: {
            defaultProps: {
                checkedIcon: <CheckboxCheckedIcon />, // this line
                color: "primary",
                icon: <CheckboxIcon />, // this
                indeterminateIcon: <CheckboxIntermediateIcon />, // this too
            },
        },
    }
}

Here's the output with turbopack (next dev --turbopack)

 ⨯ RangeError: Maximum call stack size exceeded
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:33
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
    at deepClone (C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7612:25)
    at C:\Users\Hasan Mothaffar\Documents\Work\LiveRoute\admin-web\.next\server\chunks\ssr\node_modules__pnpm_d63818._.js:7613:23
    at Array.forEach (<anonymous>)
digest: "1495935959"

Here's the output without turbopack (next dev)

⨯ node_modules\.pnpm\@[email protected]_@[email protected][email protected]\node_modules\@mui\utils\esm\deepmerge\deepmerge.js (14:1) @ eval
 ⨯ RangeError: Maximum call stack size exceeded
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
digest: "257292196"
  12 |   }
  13 |   const output = {};
> 14 |   Object.keys(source).forEach(key => {
     | ^
  15 |     output[key] = deepClone(source[key]);
  16 |   });
  17 |   return output;

@siriwatknp siriwatknp added package: utils Specific to the @mui/utils package and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Nov 11, 2024
@siriwatknp
Copy link
Member

Looks like the root cause comes from deepmerge in @mui/utils

@Akash0463
Copy link

Facing same issue after upgrading the nextjs version from 14 to 15, using @mui/material 6.1.6

@wangkailang
Copy link

+1 upgrading the nextjs version from 14 to 15, using @mui/material 5.15.11

 ⨯ ../node_modules/@mui/joy/node_modules/@mui/utils/esm/deepmerge/deepmerge.js (10:20) @ source
 ⨯ RangeError: Maximum call stack size exceeded
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
    at Array.forEach (<anonymous>)
digest: "1633909859"
   8 |   return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in item) && !(Symbol.iterator in item);
   9 | }
> 10 | function deepClone(source) {
     |                    ^
  11 |   if (!isPlainObject(source)) {
  12 |     return source;
  13 |   }

@siriwatknp siriwatknp linked a pull request Nov 13, 2024 that will close this issue
1 task
@DiegoAndai DiegoAndai moved this from Selected to In progress in Material UI Nov 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
nextjs package: utils Specific to the @mui/utils package
Projects
Status: In progress
Development

Successfully merging a pull request may close this issue.

6 participants