Cannot read properties of undefined (reading 'universal')
Describe the bug
We got the following alert in Sentry:
Reproduction
Not sure what is triggering this, if you give me a direction i can try to create a repro.
Logs
No response
System Info
System:
OS: macOS 14.5
CPU: (8) arm64 Apple M1 Pro
Memory: 121.86 MB / 16.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.11.0 - ~/.nvm/versions/node/v20.11.0/bin/node
npm: 10.2.4 - ~/.nvm/versions/node/v20.11.0/bin/npm
pnpm: 9.1.1 - /opt/homebrew/bin/pnpm
bun: 1.0.0 - ~/.bun/bin/bun
Browsers:
Brave Browser: 125.1.66.118
Chrome: 126.0.6478.61
Edge: 126.0.2592.61
Safari: 17.5
Severity
annoyance
Additional Information
No response
~~Weird. There shouldn't be a type error for reading universal if it is undefined since there's an optional chain operator (unless node is undefined)~~
EDIT: will have to look into why node is undefined here
Would probably need more details of which route the issue was reported for and the page options affecting that (prerendered, ssr, etc)
I can only imagine this was caused by some deployed version differences such as the user trying to load or preload a route client-side but the server routes were updated because of a new deployment, so it has a different manifest, then returns an undefined node.
we might have to add an undefined check for this, but it would be great if there was more information such as stack traces
Would probably need more details of which route the issue was reported for and the page options affecting that (prerendered, ssr, etc)
I can only imagine this was caused by some deployed version differences such as the user trying to load or preload a route client-side but the server routes were updated because of a new deployment, so it has a different manifest, then returns an undefined node.
we might have to add an undefined check for this, but it would be great if there was more information such as stack traces
The only page option we have defined is export const ssr = true. I cannot find a lot more information on the issue, the only stack-trace i can find is already in the picture i provided. Here's a screenshot of the Trace view of the issue, i hope this can help some more. It seems like the error was triggered 12.45 minutes after the app started loading:
Please let me know if there's anything more i can give you. We are using the session-store to force a reload of the page if a new version has been deployed + the vite:preloadError event from Vite. We do this because we have seen the "failed to load dynamically imported module" error thousands of time in our app.
Note: We added the vite:preloadError last week, which is the same time we started seeing this bug. Not sure if it's relevant, but wanted to let you know.
The only page option we have defined is
export const ssr = true.
SSR is true by default for SvelteKit, so it's likely there is a layout introducing additional page options here. I guess the most important page option would be prerender because if that's set to true you can check the html file to see if the hydration values were set correctly.
We are using the session-store to force a reload of the page if a new version has been deployed + the
vite:preloadErrorevent from Vite. We do this because we have seen the "failed to load dynamically imported module" error thousands of time in our app.Note: We added the
vite:preloadErrorlast week, which is the same time we started seeing this bug. Not sure if it's relevant, but wanted to let you know.
I wonder if it's linked to https://github.com/sveltejs/kit/issues/9089#issuecomment-1437042343 . The expected behaviour is that if a module fails to load, SvelteKit will do a version check and refresh the page. I'm more curious why that's not happening when your "failed to load dynamically imported module" errors occur. Do you have more information to share regarding that?
The only page option we have defined is
export const ssr = true.SSR is true by default for SvelteKit, so it's likely there is a layout introducing additional page options here. I guess the most important page option would be
prerenderbecause if that's set to true you can check the html file to see if the hydration values were set correctly.We are using the session-store to force a reload of the page if a new version has been deployed + the
vite:preloadErrorevent from Vite. We do this because we have seen the "failed to load dynamically imported module" error thousands of time in our app. Note: We added thevite:preloadErrorlast week, which is the same time we started seeing this bug. Not sure if it's relevant, but wanted to let you know.I wonder if it's linked to #9089 (comment) . The expected behaviour is that if a module fails to load, SvelteKit will do a version check and refresh the page. I'm more curious why that's not happening when your "failed to load dynamically imported module" errors occur. Do you have more information to share regarding that?
I checked all the routes, and the only page option we have defined is ssr. Our app is a highly interactive enterprise app that uses web-sockets, so the initial render is only our loading screen. Not sure how much that helps...
We recently migrated our Sentry from the US to EU, so i don't have any of the issues with the "failed to load dynamically imported module" errors, but since we started using vite:preloadError we've finally been able to remove the issue (it of course helps that you can do e.preventDefault() to not get the error thrown and captured, but we also know when to refresh the page). Is there a reason SvelteKit does not use vite:preloadError?
Not sure if relevant, but we usually push code to production 3-10 times a day on the Frontend, and we have the poll-interval set to 30 seconds. We also enabled Skew Protection in Vercel, but that didn't really help.
Got another error with Cannot read properties of undefined (reading 'universal') in Sentry, but this one had some more stack-traces:
I managed to get access to our old Sentry with the Failed to fetch dynamically imported module error, but there's not a lot information in our Sentry dashboard on this issue... :/
Here's a screenshot of a full trace:
I remember seeing this issue once the moment a user entered the page, i was sitting right next to the user and they got the error message during our loading screen (which is within the first seconds the user visits the page).
Any status on this issue? We're getting this error at least once a day
Any status on this issue? We're getting this error at least once a day
I was planning to try and reproduce this locally if I found some spare time. It sounds like a type of cache / deployment skew issue similar to https://github.com/sveltejs/kit/issues/9089 . Definitely going to run through the code in https://github.com/sveltejs/kit/blob/main/packages/kit/src/runtime/client/client.js to see where we could handle the failed module loads better (maybe even add a handler for vite:preload if we haven't already).
Meanwhile, I'd recommend finding a temporary workaround from the others who posted similar experiences in #9089 . Sorry I can't get to this right away 🙏🏼 I try to take coding lightly on the weekends so I don't get burnt out from the coding at work too.
Are you able to share how you have implemented the vite:preloadError event listener? I'd like to try and understand what caused the Cannot read properties of undefined (reading 'universal') error.
Are you able to share how you have implemented the vite:preloadError event listener? I'd like to try and understand what caused the
Cannot read properties of undefined (reading 'universal')error.
Inside our app.html file we have added the vite:preloadError event listener like this:
<script nonce="%sveltekit.nonce%">
/**
* @see https://vitejs.dev/guide/build.html#load-error-handling
*/
window.addEventListener('vite:preloadError', (e) => {
e.preventDefault()
window.location.reload()
});
</script>
I've found out the Cannot read properties of undefined (reading 'universal') error is caused by preventing the original error from being thrown by calling preventDefault() on the vite:preloadError event. Ordinarily, the app loads a 500 error page when it fails to load a module, exiting the navigation code early. By preventing the error from being thrown, the navigation code tries to use the module which failed to load, which masks the real issue of the module not loading (user could be offline, file may no longer be served, etc.).
I was able to reproduce this locally by building a static website, loading a page, deleting a module, and navigating to the page that tries to load the deleted module.
I'm inclined to close this issue in favour of https://github.com/sveltejs/kit/issues/9089 . As noted by https://github.com/sveltejs/kit/issues/9089#issuecomment-1435522645 the errors are a false positive since, yes the error is thrown, but SvelteKit performs a fetch() to check the version.json file and detect if there is a new deployment, then refreshes the page. Maybe these errors should be caught and handled by SvelteKit instead of going through the handleError hook?
Currently, these two scenarios are handled the same (but maybe they shouldn't be):
- both the module and the version.json fails to be fetched. This could mean that the user is offline.
- the module fails to be fetched but the version.json was successfully fetched and has not changed. This could mean that the version.json file has been cached or the asset really is missing.
What is your suggested solution to solve this @eltigerchino? If we remove this we will encounter the error mentioned in #9089 again, which is a real issue for us (we have seen users trying to load the app and get this error on load, which makes the whole application hang).
But if i get it right, doing the e.preventDefault on this error will not solve the issue, but just silence it?
But if i get it right, doing the
e.preventDefaulton this error will not solve the issue, but just silence it?
Yes, that's right. The real issue seems to be how the assets are being served. I'd recommend reviewing how the files under _app/ are served and which cache-control headers are returned from network requests.
Which adapter are you using for your app? It could also be an issue with the specific adapter since they have different strategies for serving static files. For example, if your app is using @sveltejs/adapter-node, the static files are being served with the sirv library and we might need to fix the handler code if it is the issue.
If we remove this we will encounter the error mentioned in https://github.com/sveltejs/kit/issues/9089 again, which is a real issue for us (we have seen users trying to load the app and get this error on load, which makes the whole application hang).
I'd also recommend sending a direct request for the assets that received a 404 status when SvelteKit tries to retrieve them to see if it's an issue with SvelteKit's client-side code or if the asset really is unavailable.
If a user's app experiences this issue and renders the error page while connected to the internet, it's probably not a false positive error or that the user is trying to access the resources while offline. The issue is mostly related to how the _app/immutable/ assets and version.json file are being served.
But if i get it right, doing the
e.preventDefaulton this error will not solve the issue, but just silence it?Yes, that's right. The real issue seems to be how the assets are being served. I'd recommend reviewing how the files under
_app/are served and which cache-control headers are returned from network requests.Which adapter are you using for your app? It could also be an issue with the specific adapter since they have different strategies for serving static files. For example, if your app is using
@sveltejs/adapter-node, the static files are being served with thesirvlibrary and we might need to fix the handler code if it is the issue.If we remove this we will encounter the error mentioned in #9089 again, which is a real issue for us (we have seen users trying to load the app and get this error on load, which makes the whole application hang).
I'd also recommend sending a direct request for the assets that received a 404 status when SvelteKit tries to retrieve them to see if it's an issue with SvelteKit's client-side code or if the asset really is unavailable.
If a user's app experiences this issue and renders the error page while connected to the internet, it's probably not a false positive error or that the user is trying to access the resources while offline. The issue is mostly related to how the
_app/immutable/assets andversion.jsonfile are being served.
We are using the node-adapter, and we have skew-protection enabled in our Vercel settings. The users that experience this issue will not see the error page, instead the code will just not run (or at least that is what seemed to happen when this occurred during the loading screen).
When you say "I'd also recommend sending direct request for the assets that received a 404 status when SvelteKit tries to retrieve them to see if it's an issue with SvelteKit's client-side code or if the asset really is unavailable"?, do you mean that i should try to open the resource in a separate tab and see if it exists? I've done this a couple of times, and most of the times the resource is actually found if i recall correctly. But i don't want to send you on a search for the bug by something i may recall correctly. Is there a way to reproduce this so i can check it?
We are using the node-adapter, and we have skew-protection enabled in our Vercel settings. The users that experience this issue will not see the error page, instead the code will just not run (or at least that is what seemed to happen when this occurred during the loading screen).
Curious, why use the node adapter when the vercel adapter is available?
When you say "I'd also recommend sending direct request for the assets that received a 404 status when SvelteKit tries to retrieve them to see if it's an issue with SvelteKit's client-side code or if the asset really is unavailable"?, do you mean that i should try to open the resource in a separate tab and see if it exists?
Yes, sorry. That's what I meant.
I've done this a couple of times, and most of the times the resource is actually found if i recall correctly. But i don't want to send you on a search for the bug by something i may recall correctly. Is there a way to reproduce this so i can check it?
Yes, you can load a webpage for your existing deployment then deploy a new version of your website. After the deployment has taken effect, clicking on any link of the previously opened webpage will trigger a client-side navigation, so we can observe if the Vite module preloading fails and triggers a refresh of the page. But I think Vercel skew protection is suppose to prevent this? (if it is working as intended).
We are using the node-adapter, and we have skew-protection enabled in our Vercel settings. The users that experience this issue will not see the error page, instead the code will just not run (or at least that is what seemed to happen when this occurred during the loading screen).
Curious, why use the node adapter when the vercel adapter is available?
Sorry, i meant the Vercel adapter*
When you say "I'd also recommend sending direct request for the assets that received a 404 status when SvelteKit tries to retrieve them to see if it's an issue with SvelteKit's client-side code or if the asset really is unavailable"?, do you mean that i should try to open the resource in a separate tab and see if it exists?
Yes, sorry. That's what I meant.
I've done this a couple of times, and most of the times the resource is actually found if i recall correctly. But i don't want to send you on a search for the bug by something i may recall correctly. Is there a way to reproduce this so i can check it?
Yes, you can load a webpage for your existing deployment then deploy a new version of your website. After the deployment has taken effect, clicking on any link of the previously opened webpage will trigger a client-side navigation, so we can observe if the Vite module preloading fails and triggers a refresh of the page. But I think Vercel skew protection is suppose to prevent this? (if it is working as intended).
That's what i also thought, i would imagine the skew protection to solve this problem 🤔
You can also try to reproduce it then check the Vercel logs to view in detail which assets are returning a 404 status.
We've had progress on reproducing the Failed to fetch dynamically imported module issue consistently. Read https://github.com/sveltejs/kit/issues/12592 for more info 👍
closing this in favour of https://github.com/sveltejs/kit/issues/12592