-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Describe the bug
Since @sveltejs/kit 2.7.x, using server fetch for relative asset paths in Vercel serverless functions are broken.
The Vercel logs show:
[Error: ENOENT: no such file or directory, open '/my/path/to/my/file'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/my/path/to/my/file'
}
I believe this is because since #12113, SvelteKit is now automatically trying to use
| read: createReadableStream |
You can't use
fsin edge functions.You can use it in serverless functions, but it won't work as expected, since files are not copied from your project into your deployment. Instead, use the
readfunction from$app/serverto access your files.readdoes not work inside routes deployed as edge functions (this may change in future).
Reproduction
See https://github.com/aloisklink/sveltekit-2.7.0-issue-reproduction (click the ✔️ next to each commit to view the Vercel previews), where I've made the following function handler:
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ fetch }) => {
const response = await fetch('/favicon.png');
if (response.ok) {
return new Response(await response.arrayBuffer(), {
headers: {
'Content-Type': 'image/png',
},
});
} else {
return response;
}
};For aloisklink/sveltekit-2.7.0-issue-reproduction@1d0eedf (which uses @sveltejs/kit 2.6.4), going to https://sveltekit-2-7-0-issue-reproduction-kdo5046wh.vercel.app/test works fine.
However, for aloisklink/sveltekit-2.7.0-issue-reproduction@57e0b61 (which uses @sveltejs/kit 2.7.2), going to https://sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app/test does not work, and shows the above message in the logs.
Logs
| TimeUTC | timestampInMs | requestPath | requestMethod | responseStatusCode | requestId | requestUserAgent | level | environment | branch | vercelCache | type | function | host | deploymentDomain | deploymentId | lambdaDurationInMs | lambdaRegion | lambdaMaxMemoryUsed | lambdaMemorySize | message | projectId | wafAction |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2024-10-23 13:49:51 | 1729691391283 | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app/test | GET | -10 | hnd1::iad1::7gp8h-1729691391129-928cf35942dd | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 | error | production | main | MISS | lambda | /fn | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app | dpl_Hy6L2FDdfztninZB6wnsm4b6GGck | -1 | iad1 | -1 | -1 | [Error: ENOENT: no such file or directory, open 'favicon.png'] { errno: -2, code: 'ENOENT', syscall: 'open', path: 'favicon.png' } |
prj_Vg2wuqgw7hoKpD4qvEqCkf6EEmbZ | - |
| 2024-10-23 13:49:51 | 1729691391208 | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app/test | GET | 500 | hnd1::iad1::7gp8h-1729691391129-928cf35942dd | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 | error | production | main | MISS | lambda | /fn | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app | sveltekit-2-7-0-issue-reproduction-85gm4ombo.vercel.app | dpl_Hy6L2FDdfztninZB6wnsm4b6GGck | 59 | iad1 | 82 | 1024 | [GET] /test status=500 |
prj_Vg2wuqgw7hoKpD4qvEqCkf6EEmbZ | - |
Or just the messages:
[Error: ENOENT: no such file or directory, open 'favicon.png'] { errno: -2, code: 'ENOENT', syscall: 'open', path: 'favicon.png' }
[GET] /test status=500System Info
user@pc:~/Documents/sveltekit-2.7.0-issue-reproduction (main)$ npx envinfo --system --binaries --browsers --npmPackages "{svelte,@sveltejs/*,vite}"
System:
OS: Linux 6.8 Ubuntu 24.04.1 LTS 24.04.1 LTS (Noble Numbat)
CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
Memory: 10.38 GB / 31.27 GB
Container: Yes
Shell: 5.2.21 - /bin/bash
Binaries:
Node: 20.17.0 - ~/.nvm/versions/node/v20.17.0/bin/node
npm: 10.8.2 - ~/.nvm/versions/node/v20.17.0/bin/npm
Browsers:
Brave Browser: 130.1.71.114
npmPackages:
@sveltejs/adapter-vercel: ^5.0.0 => 5.4.5
@sveltejs/kit: ^2.0.0 => 2.7.2
@sveltejs/vite-plugin-svelte: ^4.0.0 => 4.0.0
svelte: ^5.0.0 => 5.0.5
vite: ^5.0.3 => 5.4.10Severity
blocking an upgrade
Additional Information
Maybe we can partially revert the performance enhancement change to packages/kit/src/runtime/server/fetch.js in #12113. It will slow down Cloudflare/Netlify and cause extra unnecessary requests there, but I don't think it would cause any other issues.
index 7e2177d66..d21e7b10e 100644
--- a/packages/kit/src/runtime/server/fetch.js
+++ b/packages/kit/src/runtime/server/fetch.js
@@ -1,7 +1,6 @@
import * as set_cookie_parser from 'set-cookie-parser';
import { respond } from './respond.js';
import * as paths from '__sveltekit/paths';
-import { read_implementation } from '__sveltekit/server';
/**
* @param {{
@@ -97,16 +96,6 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
return new Response(state.read(file), {
headers: type ? { 'content-type': type } : {}
});
- } else if (read_implementation) {
- const length = manifest._.server_assets[file];
- const type = manifest.mimeTypes[file.slice(file.lastIndexOf('.'))];
-
- return new Response(read_implementation(file), {
- headers: {
- 'Content-Length': '' + length,
- 'Content-Type': type
- }
- });
}
return await fetch(request);Maybe adding a check to see if file in manifest._.server_assets would also work, since my .svelte-kit/output/server/manifest.js has an empty manifest._.server_assets object, but I'm not familiar with Cloudflare/Netlify, so I don't know if it will work there.
index 7e2177d66..417b59c93 100644
--- a/packages/kit/src/runtime/server/fetch.js
+++ b/packages/kit/src/runtime/server/fetch.js
@@ -97,7 +97,7 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
return new Response(state.read(file), {
headers: type ? { 'content-type': type } : {}
});
- } else if (read_implementation) {
+ } else if (read_implementation && file in manifest._.server_assets) {
const length = manifest._.server_assets[file];
const type = manifest.mimeTypes[file.slice(file.lastIndexOf('.'))];