Skip to content

@sentry/sveltekit: fetch wrapper subscribes the calling $effect to navigating, re-running it on every navigation (SvelteKit 3) #26129

Closed

Description

@jose-manuel-silva

Is there an existing issue for this?

  • I have checked for existing issues

How do you use Sentry?

Sentry SaaS (sentry.io)

Which SDK are you using?

@sentry/sveltekit

SDK Version

11.8.0 (the same code is in 11.11.0)

Framework Version

@sveltejs/kit 3.1.0, svelte 5.57.2

Description

With browser tracing on, instrumentSvelteKitTracing (packages/sveltekit/src/client/svelte5BrowserTracing.ts) replaces window.fetch with a wrapper that calls getCurrentNavigation() before every request:

WINDOW.fetch = (...args) => {
  const navigation = getCurrentNavigation();
  if (navigation) _startNavigation(navigation);
  return originalFetch(...args);
};

getCurrentNavigation() (packages/sveltekit/src/client/navigationState.svelte.ts) reads navigating.type, navigating.from and the other fields from $app/state. Those are reactive reads, and they aren't untracked. When the app calls fetch synchronously inside a $effect, which is the usual pattern, Svelte records navigating as a dependency of that effect. The effect then re-runs, and repeats its requests, when any navigation starts and again when it completes.

In practice:

  • leaving a page re-sends that page's data requests as the user navigates away (the results are thrown away);
  • a navigation that stays on the same route (e.g. only the query string changes) sends every effect-driven request twice.

None of this happens with Sentry disabled. The SvelteKit 2 / Svelte 4 path (svelte4BrowserTracing.ts, store subscriptions) isn't affected. The SvelteKit 3 path came in with #22264.

Reproduction Example/SDK Setup

// src/hooks.client.js
import * as Sentry from '@sentry/sveltekit';

Sentry.init({
  dsn: '...',
  integrations: [Sentry.browserTracingIntegration()],
  tracesSampleRate: 1
});
<!-- src/routes/a/+page.svelte -->
<script>
  let n = $state(0);
  $effect(() => {
    fetch('/api/ping').then(() => n++); // called synchronously in the effect
  });
</script>

<p>requests: {n}</p>
<a href="/b">go to b</a>
<a href="/a?x=1">same route, new query</a>

Steps to Reproduce

  1. Open /a. One request to /api/ping.
  2. Click "same route, new query". Two more requests (navigation start and navigation end).
  3. Click "go to b". /api/ping is requested again while the page is being left.

Putting $inspect.trace() inside the effect lists $state navigation (SvelteKit's internal state behind navigating) as the changed dependency on those re-runs.

Expected Result

Instrumenting fetch doesn't change the calling code's reactive dependencies: the effect runs once and re-runs only when its own inputs change.

Actual Result

Every effect that calls fetch before its first await re-runs on every navigation, the one leaving the page included.

Suggested fix

Read the navigation untracked, e.g. in navigationState.svelte.ts:

import { untrack } from 'svelte';

export function getCurrentNavigation() {
  return untrack(_snapshot);
}

(or wrap the getCurrentNavigation() call inside the fetch wrapper in untrack).

Workaround

In hooks.client.ts, after Sentry.init:

import { untrack } from 'svelte';

const sentryFetch = window.fetch;
window.fetch = (...args) => untrack(() => sentryFetch(...args));

Activity

  1. linear-code commented on Nov 5, 2026

    @linear-code
  2. self-assigned this
    on Nov 5, 2026
  3. chargome commented on Nov 5, 2026

    @chargome
    Member

    Thanks for reporting!

  4. added a commit that references this issue on Nov 6, 2026
    89d33a9
  5. added a commit that references this issue on Nov 9, 2026
    3d5ef95
  6. github-actions commented on Nov 10, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #26136, which was included in the 11.12.0 release.

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

Metadata

Metadata

Assignees

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions