S
SolidJS3d ago
Anshu

Failed to fetch errors on production

I'm capturing client exceptions on the server. Examples:
Failed to fetch dynamically imported module: https://groceryclub.shop/_build/assets/index-CI6v2rst.js
Failed to fetch dynamically imported module: https://groceryclub.shop/_build/assets/index-CI6v2rst.js
TypeError: Failed to fetch
at S (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:20545)
at D (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:20755)
at h (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:21858)
TypeError: Failed to fetch
at S (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:20545)
at D (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:20755)
at h (https://groceryclub.shop/_build/assets/server-runtime-DjtoD50O.js:1:21858)
I suspected Vercel skew. Per Vercel docs and the SvelteKit Vercel adapter, I set a cookie containing the current deployment ID so clients hit the correct deployment. my code for skew protection
export const resolveVercelSkewProtection = query(async () => {
"use server";
const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
if (!process.env.VERCEL_SKEW_PROTECTION_ENABLED || !deploymentId) return;
setCookie("__vdpl", deploymentId, {
httpOnly: false,
secure: true,
path: "/",
sameSite: "strict",
});
}, "resolve-vercel-skew-protection");
export const resolveVercelSkewProtection = query(async () => {
"use server";
const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
if (!process.env.VERCEL_SKEW_PROTECTION_ENABLED || !deploymentId) return;
setCookie("__vdpl", deploymentId, {
httpOnly: false,
secure: true,
path: "/",
sameSite: "strict",
});
}, "resolve-vercel-skew-protection");
I also send the deployment ID with each error to verify clients are on the latest deployment, so this doesn't look like a skew issue. Still, I keep getting Failed to fetch errors. I tried httpOnly: true and false with no effect. I can't reproduce locally — only remote clients report it, even with modern Chromium user agents. Originally posted: https://discord.com/channels/722131463138705510/910635844119982080/1410269726772301835
11 Replies
Madaxen86
Madaxen863d ago
I’ve been thinking about this. Where is that setCookie from? Are you sure the requests of the assets contain the cookie?
Anshu
AnshuOP3d ago
yes i am sure that request for asset contains the cookie
No description
Anshu
AnshuOP3d ago
the set cookie is from vercel skew docs https://vercel.com/docs/skew-protection and its runing at the topest layout file with deferStream
Anshu
AnshuOP3d ago
there is no change in the build, it still produces same files
Madaxen86
Madaxen863d ago
And can you also confirm that the asset is matching the deployment_id? I have the feeling that the VERCEL_DEPLOYMENT_ID gets updated, because there may be actions without revalidation keys which will invalidate all queries and update VERCEL_DEPLOYMENT_ID. Anyways a suggestion would be to put that function in the entry-server.tsx so it only runs once on each initial request, file like
// @refresh reload
import { StartServer, createHandler } from "@solidjs/start/server";

export default createHandler(() => {

const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
if (!process.env.VERCEL_SKEW_PROTECTION_ENABLED || !deploymentId) return;
setCookie("__vdpl", deploymentId, {
httpOnly: false,
secure: true,
path: "/",
sameSite: "strict",
});
return (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>

{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
);
});
// @refresh reload
import { StartServer, createHandler } from "@solidjs/start/server";

export default createHandler(() => {

const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
if (!process.env.VERCEL_SKEW_PROTECTION_ENABLED || !deploymentId) return;
setCookie("__vdpl", deploymentId, {
httpOnly: false,
secure: true,
path: "/",
sameSite: "strict",
});
return (
<StartServer
document={({ assets, children, scripts }) => (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>

{assets}
</head>
<body>
<div id="app">{children}</div>
{scripts}
</body>
</html>
)}
/>
);
});
Anshu
AnshuOP3d ago
Yes i thought so, I moved the code in entry-server.tsx But still getting these errors Failed to fetch dynamically imported module: https://groceryclub.shop/_build/assets/index-D0n0UOzW.js
ts const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
const isSkewProtectionEnabled =
process.env.VERCEL_SKEW_PROTECTION_ENABLED === "1";

if (
deploymentId &&
isSkewProtectionEnabled &&
context.request.headers.get("sec-fetch-dest") === "document"
) {
setCookie("__vdpl", deploymentId, {
path: "/",
secure: true,
sameSite: true,
httpOnly: true,
});
}
ts const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
const isSkewProtectionEnabled =
process.env.VERCEL_SKEW_PROTECTION_ENABLED === "1";

if (
deploymentId &&
isSkewProtectionEnabled &&
context.request.headers.get("sec-fetch-dest") === "document"
) {
setCookie("__vdpl", deploymentId, {
path: "/",
secure: true,
sameSite: true,
httpOnly: true,
});
}
This is my code in entry-server.tsx
Madaxen86
Madaxen863d ago
Getting these errors by customers (they might still be on an old deployment) or by youryelf?
Anshu
AnshuOP3d ago
true they might be on old deployment, getting these errors from users these links are 404 in current deployment https://groceryclub.shop/_build/assets/index-D0n0UOzW.js this request is coming from a deployment made a day ago and that makes sense cause vercel only do skew protection for 12h then what can be the solution for this ? i think quick fix can be if error contains fetch failed then we should hard reload
Madaxen86
Madaxen863d ago
Yeah either this or in your root layout inside onMount you put a setInterval which revalidates a server function that fetches the current deployment ID and compares it with the one in the cookie. If they don’t match you can do the hard reload. Interval could be something like 11:50 hours to avoid running out of the deployment skew. Additionally add a eventlistener e.g.
const newAppUpdateAvailable = createAsync(() => getAppUpdateAvailable(location.pathname)
);

onMount(() => {
function revalidateAppVersion() {
if (!document.hidden) {
revalidate(getAppUpdateAvailable.key);
}
}
document.addEventListener("visibilitychange", revalidateAppVersion);

//refresh the token every ~ 2 hours
const interval = setInterval(revalidateAppVersion, 1000 * 60 * 60 * 2);

onCleanup(() => {
document.removeEventListener("visibilitychange", revalidateAppVersion);
clearInterval(interval);
});
});
const newAppUpdateAvailable = createAsync(() => getAppUpdateAvailable(location.pathname)
);

onMount(() => {
function revalidateAppVersion() {
if (!document.hidden) {
revalidate(getAppUpdateAvailable.key);
}
}
document.addEventListener("visibilitychange", revalidateAppVersion);

//refresh the token every ~ 2 hours
const interval = setInterval(revalidateAppVersion, 1000 * 60 * 60 * 2);

onCleanup(() => {
document.removeEventListener("visibilitychange", revalidateAppVersion);
clearInterval(interval);
});
});
Anshu
AnshuOP2d ago
alright, i get the whole issue now. i did some tests and find out that even skew protection was on, it was returning 404 for old files. after i cleared the cache in vercel, skew protection started working. so this confirms that clients are either running on latest version with no errors or client running on some version where skew expired after 12 hours so all the errors i am getting now on server are users that running version created before 12 hours. i just need to implement that version checker and then show a notification to user that new version avilable, reload now also whenever i get these dynamic failed errors i should hard reload by JS thanks @Madaxen86 for all your help :v

Did you find this page helpful?