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

server fetch for relative asset paths in Vercel are broken since @sveltejs/kit 2.7.0 #12868

Closed
aloisklink opened this issue Oct 23, 2024 · 2 comments · Fixed by #12876
Closed
Labels
pkg:adapter-vercel Pertaining to the Vercel adapter

Comments

@aloisklink
Copy link
Contributor

aloisklink commented Oct 23, 2024

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
, but as stated in the Vercel docs page:

You can't use fs in 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 read function from $app/server to access your files. read does 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=500

System 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.10

Severity

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('.'))];
@benmccann benmccann added the pkg:adapter-vercel Pertaining to the Vercel adapter label Oct 23, 2024
@eltigerchino
Copy link
Member

eltigerchino commented Oct 25, 2024

Could this be due to the changes to the fetch function? https://github.com/sveltejs/kit/pull/12113/files#diff-dec395f95c73993337a75dc66fbb8d9b128859fdcc0729a9218f6481e5eac21a
cc: @mastermakrela @dummdidumm

} 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
}
});
}

@mastermakrela
Copy link
Contributor

Sorry for late answer, I didn't have time to look into it earlier 😅

The merged solution looks good, and I've confirmed that it still works in Cloudflare :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg:adapter-vercel Pertaining to the Vercel adapter
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants