sveltejs/svelte · error · Error

fork_timing

fork_timing

Error message

fork_timing
Cannot create a fork inside an effect or when state changes are pending
https://svelte.dev/e/fork_timing

What it means

Thrown at reactivity/batch.js:1381 inside fork() when current_batch is non-null at the moment of calling. A fork snapshots the current state graph and must run in a clean (non-flushing) environment; creating one while a batch is mid-flush or while state changes are pending would fork an inconsistent snapshot.

Source

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

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

/**
 * Cannot create a fork inside an effect or when state changes are pending
 * @returns {never}
 */
export function fork_timing() {
	if (DEV) {
		const error = new Error(`fork_timing\nCannot create a fork inside an effect or when state changes are pending\nhttps://svelte.dev/e/fork_timing`);

		error.name = 'Svelte error';

		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`);
	}
}

View on GitHub (pinned to 20b341f100)

Solutions

  1. Move the fork() call out of any effect — call it from a plain event handler or top-level action that runs when no batch is active.
  2. Defer the fork with queueMicrotask or setTimeout(0) so it runs after the current flush completes.
  3. Restructure so speculative state is computed via $derived rather than forked mid-flush.

Example fix

// before
$effect(() => {
  const f = fork(() => { speculative = data(); }); // current_batch active
});

// after
function navigate() {
  const f = fork(() => { speculative = data(); }); // called from event, no batch
  // ...
}
Defensive patterns

Strategy: validation

Validate before calling

// Only call fork() from a non-reactive context (event handler, top-level action).
// Avoid calling fork() from inside $effect/$derived bodies.
// If unsure, defer:
function safeFork(fn) {
  queueMicrotask(() => fork(fn));
}

Prevention

When it happens

Trigger: Calling fork() from inside a $effect (which runs during a batch flush), from within another fork's initialiser, or at a moment when a pending state write has not yet been flushed. The guard at batch.js:1380-1382 checks current_batch!==null.

Common situations: Speculative navigation forks triggered from within an effect; calling fork() in a reactive callback that fires during update flush; event handlers that fire synchronously during a batched update.

Related errors


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