sveltejs/svelte · error · Error

get_abort_signal_outside_reaction

get_abort_signal_outside_reaction

Error message

get_abort_signal_outside_reaction
`getAbortSignal()` can only be called inside an effect or derived
https://svelte.dev/e/get_abort_signal_outside_reaction

What it means

Thrown at index-client.js:71 inside getAbortSignal() when active_reaction is null. getAbortSignal returns an AbortController signal tied to the current effect/derived lifecycle so async work is cancelled on re-run or teardown; without an active reaction there is no lifecycle to bind it to.

Source

Thrown at packages/svelte/src/internal/client/errors.js:311

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/fork_timing`);
	}
}

/**
 * `getAbortSignal()` can only be called inside an effect or derived
 * @returns {never}
 */
export function get_abort_signal_outside_reaction() {
	if (DEV) {
		const error = new Error(`get_abort_signal_outside_reaction\n\`getAbortSignal()\` can only be called inside an effect or derived\nhttps://svelte.dev/e/get_abort_signal_outside_reaction`);

		error.name = 'Svelte error';

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/get_abort_signal_outside_reaction`);
	}
}

/**
 * Expected to find a hydratable with key `%key%` during hydration, but did not.
 * @param {string} key
 * @returns {never}
 */
export function hydratable_missing_but_required(key) {
	if (DEV) {
		const error = new Error(`hydratable_missing_but_required\nExpected to find a hydratable with key \`${key}\` during hydration, but did not.\nhttps://svelte.dev/e/hydratable_missing_but_required`);

		error.name = 'Svelte error';

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/hydratable_missing_but_required`);
	}

View on GitHub (pinned to 20b341f100)

Solutions

  1. Call getAbortSignal() only from within a $derived (e.g. `const data = $derived(await getData(id))`) or a $effect.
  2. Pass the signal down from the effect/derived rather than calling getAbortSignal in a leaf utility.
  3. If you need cancellation outside reactivity, construct your own AbortController and manage its lifecycle.

Example fix

// before
async function loadData(id) {
  const res = await fetch(`/api/${id}`, { signal: getAbortSignal() });
  return res.json();
}
// called from a plain event handler — no active reaction

// after — call from a $derived so a reaction is active
const data = $derived(loadData(id));
// loadData now runs inside the derived, getAbortSignal has a reaction
Defensive patterns

Strategy: validation

Validate before calling

// Only call getAbortSignal() from inside a $derived or $effect.
// For utilities, accept an explicit signal argument instead:
async function loadData(id, signal) {
  const res = await fetch(`/api/${id}`, { signal });
  return res.json();
}
// caller: const data = $derived(loadData(id, getAbortSignal()));

Prevention

When it happens

Trigger: Calling getAbortSignal() in module scope, in a plain function not invoked from an effect/derived, in an event handler, or after the component finished initialising. The guard at index-client.js:70-72 checks active_reaction===null.

Common situations: Calling getAbortSignal() inside a plain async utility imported from a .js file; using it in an onMount-style function that runs outside a derived; refactoring data fetching out of a $derived into a plain function.

Related errors


AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12). Data as JSON: /api/errors/36cbae547f736364. Report an issue: GitHub.