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

[Bug]: TypeError: Cannot read properties of undefined (reading 'root') #1618

Closed
adrianiskandar opened this issue Jan 23, 2022 · 34 comments · Fixed by #2403
Closed

[Bug]: TypeError: Cannot read properties of undefined (reading 'root') #1618

adrianiskandar opened this issue Jan 23, 2022 · 34 comments · Fixed by #2403
Labels
enhancement New feature or request feat:dx Issues related to the developer experience

Comments

@adrianiskandar
Copy link

adrianiskandar commented Jan 23, 2022

Which Remix packages are impacted?

  • remix (Remix core)

What version of Remix are you using?

"remix": "^1.1.3",

What version of Node are you using? Minimum supported version is 14.

v16.4.2

Steps to Reproduce

I was just trying to follow the first tutorial, and right after the part when you create the posts .md files everything was working ok. But after you add the code mentioned in the tutorial:

import path from 'path';
import fs from 'fs/promises';
import parseFrontMatter from 'front-matter';
import invariant from 'tiny-invariant';

export type Post = {
  slug: string;
  title: string;
};

export type PostMarkdownAttributes = {
  title: string;
};

const postsPath = path.join(__dirname, '..', 'posts');

function isValidPostAttributes(attributes: any): attributes is PostMarkdownAttributes {
  return attributes?.title;
}

export async function getPosts() {
  const dir = await fs.readdir(postsPath);
  return Promise.all(
    dir.map(async (filename) => {
      const file = await fs.readFile(path.join(postsPath, filename));
      const { attributes } = parseFrontMatter(file.toString());
      invariant(isValidPostAttributes(attributes), `${filename} has bad meta data!`);
      return {
        slug: filename.replace(/\.md$/, ''),
        title: attributes.title,
      };
    })
  );
}

Then the application breaks and starts showing this error on localhost/posts

TypeError: Cannot read properties of undefined (reading 'root')
    at RemixRoute (http://10.0.0.229:3000/build/_shared/chunk-EW2HPZY2.js:3039:19)
    at renderWithHooks (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:11070:26)
    at mountIndeterminateComponent (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:13190:21)
    at beginWork (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:13977:22)
    at HTMLUnknownElement.callCallback2 (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3680:22)
    at Object.invokeGuardedCallbackDev (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3705:24)
    at invokeGuardedCallback (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3739:39)
    at beginWork$1 (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:17086:15)
    at performUnitOfWork (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:16314:20)
    at workLoopSync (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:16268:13)

The error is not helpful at all so I spend some time debugging it and I find out that it was because the <Scripts /> component in the root.tsx file

import { Link, Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from 'remix';
import type { MetaFunction } from 'remix';

export const meta: MetaFunction = () => {
    return { title: 'New Remix App' };
};

export default function App() {
    return (
        <html lang="en">
            <head>
                <meta charSet="utf-8" />
                <meta name="viewport" content="width=device-width,initial-scale=1" />
                <Meta />
                <Links />
            </head>
            <body>
                <Link to="/posts">Posts</Link>
                <Outlet />
                <ScrollRestoration />
                {/* <Scripts /> */}
                {process.env.NODE_ENV === 'development' && <LiveReload />}
            </body>
        </html>
    );
}

If you comment out the <Scripts /> tag the app starts working again but still don't know exactly why

Expected Behavior

The app should not break or it should show a helpful error that helps identify the bug

Actual Behavior

The app breaks showing this error:

TypeError: Cannot read properties of undefined (reading 'root')
    at RemixRoute (http://10.0.0.229:3000/build/_shared/chunk-EW2HPZY2.js:3039:19)
    at renderWithHooks (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:11070:26)
    at mountIndeterminateComponent (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:13190:21)
    at beginWork (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:13977:22)
    at HTMLUnknownElement.callCallback2 (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3680:22)
    at Object.invokeGuardedCallbackDev (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3705:24)
    at invokeGuardedCallback (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:3739:39)
    at beginWork$1 (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:17086:15)
    at performUnitOfWork (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:16314:20)
    at workLoopSync (http://10.0.0.229:3000/build/entry.client-X6Z7634E.js:16268:13)
@adrianiskandar adrianiskandar added the bug Something isn't working label Jan 23, 2022
@spicelander
Copy link

I am having the same error. Strangely mine happens after making a call to firebase firestore (using firebase-admin). Error goes away when I comment out the tag as well.

@Andreychik32
Copy link

I have the same error too after adding framer-motion to my code.

<motion.div animate={{ rotate: 360 }} transition={{ duration: 2 }}>
    <h1>Welcome to remix!</h1>
</motion.div>

results in:

TypeError: Cannot read properties of undefined (reading 'root')
    at RemixRoute (http://localhost:3000/build/_shared/chunk-4FUSWSXW.js:3039:19)
    at renderWithHooks (http://localhost:3000/build/entry.client-ZTUCAJA4.js:11070:26)
    at mountIndeterminateComponent (http://localhost:3000/build/entry.client-ZTUCAJA4.js:13190:21)
    at beginWork (http://localhost:3000/build/entry.client-ZTUCAJA4.js:13977:22)
    at HTMLUnknownElement.callCallback2 (http://localhost:3000/build/entry.client-ZTUCAJA4.js:3680:22)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/build/entry.client-ZTUCAJA4.js:3705:24)
    at invokeGuardedCallback (http://localhost:3000/build/entry.client-ZTUCAJA4.js:3739:39)
    at beginWork$1 (http://localhost:3000/build/entry.client-ZTUCAJA4.js:17086:15)
    at performUnitOfWork (http://localhost:3000/build/entry.client-ZTUCAJA4.js:16314:20)
    at workLoopSync (http://localhost:3000/build/entry.client-ZTUCAJA4.js:16268:13)

@kiliman
Copy link
Collaborator

kiliman commented Jan 25, 2022

This error typically occurs when you have server side dependencies that got bundled in your client scripts. The file with the getPosts() function, what is it named? Does it use the .server suffix, like posts.server.ts? This tells the Remix compiler all this code is only used on the server.

https://remix.run/docs/en/v1/guides/constraints

@Andreychik32
Copy link

Andreychik32 commented Jan 25, 2022

@kiliman, that was my case, as I've added some prisma code to my app and haven't noticed that it broke it.
Thank you for your advice 😅

@giotramu
Copy link

I had the same issue, but the @kiliman solution worked for me. I renamed the file from index.ts to index.server.ts.

@nhein-tt
Copy link

I'm having this problem as well, however my file already has the .server prefix.

https://github.com/nheingit/blog

This is the repo for the code.

The error occurs on /blog/test-mdx

Everything renders correctly, but I still get the error message.

Screen Shot 2022-01-26 at 12 03 06 PM

@kiliman
Copy link
Collaborator

kiliman commented Jan 26, 2022

I actually tried your example, both with netlify and using Remix App Server... looks like routeModules is not being defined in the Remix Context. Not sure what's causing this. I'll dig deeper once I have some time.

This should not be undefined, but should have the value that's initially set via SSR. This is why you get the exception, as it's trying to get routeModules['root']
image

image

@nhein-tt
Copy link

@kiliman Thanks for the response! Let me know if I can be of any help.

@yomeshgupta
Copy link
Contributor

I am getting the same error. I tried debugging and I found the same issue that routeModules is coming out as undefined. Any idea why this might be happening?

Following is the url where I am getting the error --
https://devtools.tech/questions/s/how-would-you-implement-createstore-function-from-redux---qid---gDe2UTYeJi0ptBXfuLXL

Couple of pointers:

  1. Issue is happening intermittently.
  2. If I throttle the network then issue starts coming up i.e. mostly happens on slow network.
  3. In my case, I am using ACE Editor and it breaks when it comes to SSR so I have put it behind a document check guard. If document is undefined then I render static UI else ACE editor. So, SSR HTML changes after hydration.

Let me know if I can help in some way. Thanks!

@kiliman
Copy link
Collaborator

kiliman commented Jan 28, 2022

I believe the issue arises because the browser is processing that module, and it tries to import the routes. However, something is failing in the route module. Most likely server code got bundled with the client. Because it fail loading, it stops executing that module and never runs the statement that initializes the window.__remixRouteModules.

I suggest that the code that initializes RemixEntryContext should probably check to see if routeData and routeModules are properly defined, and throw an error with the message 'Cannot initialize routeModules. This normally occurs when you have server code in your client modules. See this link for more details: '

At least that's a better error than this cryptic message. I'm not sure if you can wrap import statements in try/catch.

@nhein-tt
Copy link

@killman would like to follow up on this.

If all of this is true, I'm bundling server code into my client somewhere. However, my imports do have the .server suffix, which afaik should signal to remix that this info SHOULDN'T be bundled to the browser.

Any ideas as to what is causing my underlying issue?

@nhein-tt
Copy link

Update: I was also importing path and fs in my loader, and so those were getting bundled in as well.

After setting up a .server.ts file where I can import all of my server code, and then import from THERE, everything works.

@matt-koevort
Copy link

I'm getting the same error when trying to introduce components that use react-three-fiber. Assuming they are packaged with node-only APIs or something along those lines?

@chooie
Copy link

chooie commented Feb 2, 2022

I ran into this issue as well when trying to port code to another repo.

The fix for me was to add this to package.json:

"sideEffects": false

It seems to be what Remix needs in order to properly strip out server code in the client (tree-shaking). I noticed the error would occur for every file in app/routes/ that imported a server file.

@Yelmuf
Copy link

Yelmuf commented Feb 2, 2022

Was experiencing this issue in Remix + MUI example. PR mentioned above helped, thanks!

In my case it was

import * as React from 'react'

Files with this import were used in SSR. Refactored to using named imports and everything works.

@samstanding22
Copy link

Update: I was also importing path and fs in my loader, and so those were getting bundled in as well.

After setting up a .server.ts file where I can import all of my server code, and then import from THERE, everything works.

Was running into the same issue trying to import Airtable into my loader. This solved it.

@dillionmegida
Copy link

dillionmegida commented Feb 14, 2022

Just came across this issue while experiencing the same thing. In my case, I'm not doing any server-side thing. I'm just creating a websocket and calling APIs, right when the component has mounted on the browser.

I also tried doing:

export default function Index() {
    // ..
    if (typeof document === 'undefind') return <></>

    // render component
}

but it still didn't work. Is there any way we can inspect the routeModules? That is undefined for me too.

@yomeshgupta
Copy link
Contributor

yomeshgupta commented Feb 14, 2022

@dillionmegida From my understanding, this issue can also come up if any JS is breaking in this particular component. Check the developer console to see if there are any JS errors proceeding this error. If yes, fixing those might resolve the issue.

Also, you can move your code into client-only module to make it exclusively run in the browser. Check this --

https://devtools.tech/blog/how-to-fix-errors-like-referenceerror-window-is-not-defined-in-remix-powered-web-app-or-javascript-frameworks---rid---G0OTehUXo6QQCrfykSF3

@wolfhoundjesse
Copy link

Just came across this issue while experiencing the same thing. In my case, I'm not doing any server-side thing. I'm just creating a websocket and calling APIs, right when the component has mounted on the browser.

I also tried doing:

export default function Index() {
    // ..
    if (typeof document === 'undefind') return <></>

    // render component
}

but it still didn't work. Is there any way we can inspect the routeModules? That is undefined for me too.

What are the chances that the typo in your code here is also in your code there? Because that's exactly what would happen to me somehow. lol

@na2axl
Copy link

na2axl commented Feb 22, 2022

I also have this error, but on my side, I've just added a resource route. It's only when I add a default function to the resource route file that my app works again.

@epitaphmike
Copy link

This occurs for me when importing an Icon from @heroicons, but only in my Vercel build and not a traditional Remix build
import { ExclamationIcon } from '@heroicons/react/solid';

In the @heroicons library the icons *.d.ts file uses import * as React from 'react

@epitaphmike
Copy link

Adding import * as React from 'react'; to the client file stops the error, but this still doesn't seem right.

@massimopalmieri
Copy link

I'm experiencing the same issue.
@heroicons works fine until I import @react-pdf and @react-pdf also works if I remove the @heroicons import

@machour
Copy link
Collaborator

machour commented Mar 18, 2022

The original issue reported is now covered in the gotcha section

@machour machour closed this as completed Mar 18, 2022
@machour machour added docs and removed bug Something isn't working labels Mar 18, 2022
@kiliman
Copy link
Collaborator

kiliman commented Mar 18, 2022

I get that this is a common issue and mentioned in the docs. However, the error message itself is misleading, because Remix isn't verifying that routeModules is defined.

If the code added a check and threw a more meaningful error, this wouldn't be so confusing to first time users.

From comment above:

I suggest that the code that initializes RemixEntryContext should probably check to see if routeData and routeModules are properly defined, and throw an error with the message 'Cannot initialize routeModules. This normally occurs when you have server code in your client modules. See this link for more details (link to gotcha section)'

@machour machour reopened this Mar 18, 2022
@machour machour added enhancement New feature or request and removed docs labels Mar 18, 2022
@machour
Copy link
Collaborator

machour commented Mar 18, 2022

You're totally right @kiliman, keeping this open and accepting PRs 🙏🏼

@machour machour added the PR Welcome We would love a PR addressing this issue label Mar 18, 2022
@machour machour added feat:dx Issues related to the developer experience and removed PR Welcome We would love a PR addressing this issue labels Mar 20, 2022
@machour machour closed this as completed Mar 31, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Apr 6, 2022

🤖 Hello there,

We just published version v1.3.5-pre.0 which involves this issue. If you'd like to take it for a test run please try it out and let us know what you think!

Thanks!

@jbasdf
Copy link

jbasdf commented Apr 30, 2022

I'm running into this same error. I've deployed a Remix site to Cloudflare pages. Everything works fine in Chrome and Safari. Firefox give me the following error:

Error: Cannot initialize 'routeModules'. This normally occurs when you have server code in your client modules.
Check this link for more details:
https://remix.run/pages/gotchas#server-code-in-client-bundles

Interestingly this only happens in Firefox when I visit a specific page and only if I use a custom domain. If I use the workers.dev domain provided by Cloudflare the page loads fine.

@jbasdf
Copy link

jbasdf commented Apr 30, 2022

I did some more testing and found that turning off the Cloudflare 'Rocket Loader' under speed optimizations fixed the problem in Firefox. I'm guessing in my case this is a Cloudflare bug.

@louisjrdev
Copy link

Encountered a similar error to this when using third party components react-select and react-datepicker. Add a import * as React from 'react';

Could we re-open, or open a new issue for this as it is still causing problems.

@machour
Copy link
Collaborator

machour commented May 29, 2022

@louisjrdev This is now a documented gotcha (see docs) and the error message was enhanced.

Feel free to open a new issue if you thing something is broken, and not covered by the documentation.

@louisjrdev
Copy link

@machour There is certainly still a bug here, I should not have to import * as React from 'react'; to mitigate this, I am importing no server code and the only thing that makes the error go away is the above import.

@machour
Copy link
Collaborator

machour commented May 29, 2022

@louisjrdev this is not what this issue was about, please read the originally reported problem, that's what we fixed.
You're in a different setup, so by all means, please open a new issue :)

phollome added a commit to mint-vernetzt/community-platform that referenced this issue Aug 24, 2022
phollome added a commit to mint-vernetzt/community-platform that referenced this issue Aug 24, 2022
* implement set or unset parent event
* fix: cannot read properties of undefined (reading: 'root')
see remix-run/remix#1618 (comment)
* show parent and child events
* create parent or child event
* warn that child events were deleted
* fix: TypeError: Invalid URL: /event/create
* fix: Array.prototype.map() expects a return value from arrow
* add missing anon test
* implement add child event
* implement remove child event
* filter events having parent
* fix: test checking options failed
* publish recursive
@martinmckenna
Copy link

I did some more testing and found that turning off the Cloudflare 'Rocket Loader' under speed optimizations fixed the problem in Firefox. I'm guessing in my case this is a Cloudflare bug.

omfg thank you for posting this. I've been having the same issue for WEEKS!!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feat:dx Issues related to the developer experience
Projects
None yet
Development

Successfully merging a pull request may close this issue.