sveltejs/kit · warning

Can only disable scroll handling during navigation

Error message

Can only disable scroll handling during navigation

What it means

`disableScrollHandling()` only works synchronously during a client-side navigation update (i.e. from `load`, `onMount` during navigation, `afterNavigate`, or an action while navigation is in progress). In DEV, calling it outside that window throws, because there is no in-flight navigation whose scroll behavior can be changed.

Source

Thrown at packages/kit/src/runtime/client/client.js:2622

 *
 * If a function (or a `Promise` that resolves to a function) is returned from the callback, it will be called once the DOM has updated.
 *
 * `onNavigate` must be called during a component initialization. It remains active as long as the component is mounted.
 * @param {(navigation: OnNavigate) => import('types').MaybePromise<(() => void) | void>} callback
 * @returns {void}
 */
export function onNavigate(callback) {
	add_navigation_callback(on_navigate_callbacks, callback);
}

/**
 * If called when the page is being updated following a navigation (in `onMount` or `afterNavigate` or an action, for example), this disables SvelteKit's built-in scroll handling.
 * This is generally discouraged, since it breaks user expectations.
 * @returns {void}
 */
export function disableScrollHandling() {
	if (DEV && started && !updating) {
		throw new Error('Can only disable scroll handling during navigation');
	}

	if (updating || !started) {
		autoscroll = false;
	}
}

let warned_on_invalidate_all = false;
let warned_on_replace_state = false;
let warned_on_push_state = false;
let warned_on_replace_state_function = false;

/**
 * @param {string | URL} url
 * @param {'goto' | 'pushState' | 'replaceState'} caller
 */
async function resolve_intent(url, caller) {
	const resolved = new URL(resolve_url(url));

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Call `disableScrollHandling()` synchronously at the top of a `load` function (non-deferred)
  2. Alternatively use `<a data-sveltekit-noscroll>` on the link instead of calling the function
  3. If you need post-navigation control, use `goto(url, { noScroll: true })` or `invalidate(..., { noScroll })` style options rather than the function after the fact

Example fix

// before
export const load = async ({ fetch }) => {
  const data = await fetch('/api').then((r) => r.json());
  disableScrollHandling();
  return data;
};
// after
export const load = () => {
  disableScrollHandling();
  return { }; // sync call before any await/defer
};
Defensive patterns

Strategy: validation

Validate before calling

import { dev } from '$app/environment';
function safeDisableScrollHandling(disableScrollHandling, updating, started) {
  if (dev && started && updating) disableScrollHandling();
  else console.warn('disableScrollHandling ignored outside navigation');
}

Type guard

const canDisableScroll = (started, updating) => started && updating;

Try / catch

try {
  disableScrollHandling();
} catch (e) {
  if (e.message.includes('during navigation')) {
    // use data-sveltekit-noscroll or goto(url, { noScroll: true }) instead
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `disableScrollHandling()` in a `setTimeout`/`await`-deferred callback, in an event handler, in `afterNavigate` after the update finished, or on first page load after hydration (`started && !updating`).

Common situations: Calling it after awaiting data in `load`; calling from a click handler to stop scroll jumps; calling in `afterNavigate` when the navigation already completed.

Related errors


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/34ab32242a1c05d7. Report an issue: GitHub.