Skip to content

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

@aloisklink

Description

@aloisklink

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('.'))];

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions