TypeError: Fetch failed in SvelteKit server-side rendering - Express does not show a proper TypeScript stack trace
Asked Answered
O

3

9

I am checking the logs of the SvelteKit SSR server using adapter-node.

I have customised the server.js to use Express instead of Polka, though not sure if this matters.

There are apparent errors which I believe is when fetch() tries to read data from backend API and fails for some reason.

This is the console output from I get using docker:

frontend  | TypeError: fetch failed
frontend  |     at fetch (file:///app/build/handler.js:17895:14)
frontend  |     at async Object.fetch (file:///app/build/server/index.js:2273:12)
frontend  |     at async fetch (file:///app/build/server/index.js:991:24)
frontend  |     at async Promise.all (index 0)
frontend  |     at async load (file:///app/build/server/chunks/6-0becfa88.js:8:56)
frontend  |     at async load_data (file:///app/build/server/index.js:1088:16)
frontend  |     at async file:///app/build/server/index.js:1887:18

This stack trace is unusable, because it lacks the information of what was the function / source code that called fetch(). Not sure if this is because of how Node.js / Express works, or because lack of TypeScript source map support in some part of the stack or something else. A SvelteKit project has dozens of functions called load() because that is what every router endpoint has.

What would be a way to make these errors, and SvelteKit error handling in general, more descriptive - e.g. to show the proper caller mapped to its TypeScript source file, the failed page name, failed URL in fetch() and so on? This would then help to diagnose the underlying problem of what could be wrong with the API calls that fail.

Oscillogram answered 16/1, 2023 at 17:55 Comment(2)
This has been a bit of a pain point for me as well. Debugging the built code for Node.js is pretty tricky. You can comb through the built code and you might find some esbuild tags that could point you in the right direction. – Winston
async is a tool of a devil and the root cause of undebuggabilty. However, SvelteKit is now 1.0 and more and more people face this issue. Well-known or de facto standard solutions should be developing as we speak. – Oscillogram
A
4

The problem might be lacking of sourcemap.

When SvelteKit builds your app, it gonna split your code into several chunks which makes unusable error stack trace.

There is a way to enable sourcemap again and you can try that on your project to see if it works.

  1. Modify vite.config.xx file, add below config:
const config = {
  ...
  build:{
    sourcemap: true // Config vite to generate sourcemap when bundling.
  },
  ...
}
  1. Add sourcemap flag when starting node, for example:
node index.js --enable-source-maps

This should make your stack trace pointing to your src instead of build. You can try and check out whether your project is still printing unmeaningful stack trace.

Ataliah answered 22/1, 2023 at 15:30 Comment(3)
Unfortunately, there is an open issue with Vite (and thus SvelteKit) that prevents source maps from being loaded: github.com/vitejs/vite/issues/3288 – Gametogenesis
πŸ₯² oh snap - manual logging decoration it is then – Oscillogram
That issue is about debugging. Server-side runtime stack traces use source maps just fine for me. I didn't need to specifically enable them in vite.config (that controls generation of client-side source maps), but I did need to put the --enable-source-maps before the script name, i.e.: node --enable-source-maps build/ – Anchoveta
G
4

You can define handleFetch() inside src/hooks.server.ts. Then log both the requested URL and page from there:

// src/hooks.server.js

/** @type {import('@sveltejs/kit').HandleFetch} */
export function handleFetch({ event, request, fetch }) {

  let fetchResult;
  try {
      fetchResult = await fetch(request);
  } catch (error) {
      // Log info from event and request here.
  }

  return fetchResult;
}
Gametogenesis answered 20/1, 2023 at 12:48 Comment(2)
Thank you Leftium. This is quite excessive logging. Would you know if there is more generic solution available that would simply show the descriptive stack trace where the fetch() failed? – Oscillogram
You can wrap fetch() in a try block and only log when it fails. I updated my answer. If fetch() doesn't throw an error, just check for the error status and log accordingly. @MikkoOhtamaa – Gametogenesis
A
4

The problem might be lacking of sourcemap.

When SvelteKit builds your app, it gonna split your code into several chunks which makes unusable error stack trace.

There is a way to enable sourcemap again and you can try that on your project to see if it works.

  1. Modify vite.config.xx file, add below config:
const config = {
  ...
  build:{
    sourcemap: true // Config vite to generate sourcemap when bundling.
  },
  ...
}
  1. Add sourcemap flag when starting node, for example:
node index.js --enable-source-maps

This should make your stack trace pointing to your src instead of build. You can try and check out whether your project is still printing unmeaningful stack trace.

Ataliah answered 22/1, 2023 at 15:30 Comment(3)
Unfortunately, there is an open issue with Vite (and thus SvelteKit) that prevents source maps from being loaded: github.com/vitejs/vite/issues/3288 – Gametogenesis
πŸ₯² oh snap - manual logging decoration it is then – Oscillogram
That issue is about debugging. Server-side runtime stack traces use source maps just fine for me. I didn't need to specifically enable them in vite.config (that controls generation of client-side source maps), but I did need to put the --enable-source-maps before the script name, i.e.: node --enable-source-maps build/ – Anchoveta
V
1

Check Your server's environment variable, did you put NODE_ENV = 'production' on the server, it could be expecting that but got 'development' instead therefor the url will http://localhost which will cause fetch error

Vrablik answered 9/11, 2023 at 19:11 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.