Skip to content

Failed link preload leaves an unhandled rejection in production builds (3.0.0-next.27) #17178

Description

@scherning

Describe the bug

With link preloading on (data-sveltekit-preload-data="hover"), a failed data request for a hovered link leaves an unhandled promise rejection in production builds.

When the __data.json request for the preloaded route fails (the network drops or cancels it), load_route passes the error through handleError and then, because the load is a preload, rethrows the handled App.Error:

if (preload && preload_tokens.has(preload)) {
	throw await handle_error(err, { params, url, route: { id: route.id } });
}

In development the hover handler catches this (void _preload_data(intent).catch(...), which logs the preload warning). The production branch is void _preload_data(intent); with no handler, so the rejection is unhandled.

Anything listening for unhandledrejection, such as an error tracker's default global handlers, then records a second event for the same failure: a plain object like {"status":500,"message":"Internal Error"} with no stack, after handleError has already reported the real error. preloadData() catches the same throw and returns { type: 'error' }, so only the hover/tap path is affected. The 2.x line returns a preload_error(...) result instead of throwing, so it does not have this problem.

Reproduction

  1. A page with a link to another route whose load runs on the server (so the preload fetches __data.json), and data-sveltekit-preload-data="hover" on <body>.
  2. vite build && vite preview.
  3. Register window.addEventListener('unhandledrejection', (e) => console.log(e.reason)).
  4. Make the target's __data.json request fail — DevTools request blocking, or in Playwright page.route((url) => url.pathname.endsWith('/__data.json'), (route) => route.abort('failed')) — then hover the link.

The listener logs the handled App.Error object. Under vite dev the same steps only print the preload warning.

Logs

unhandledrejection: {"status":500,"message":"Internal Error"}

System Info

@sveltejs/kit 3.0.0-next.27
svelte 5.57.0
vite 8.2.2
@sveltejs/vite-plugin-svelte 7.3.0
Chromium (Playwright 1.63.0)

Severity

annoyance

Additional Information

Catching in the production branch the way the development branch does fixes it for us — the error has already been through handleError:

} else {
	void _preload_data(intent).catch(noop);
}

We carry that as a local patch for now. Porting the 2.x preload_error approach would also work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions