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
- 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.
- Defer the fork with queueMicrotask or setTimeout(0) so it runs after the current flush completes.
- 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
- Call fork() from user-triggered event handlers, not from effects.
- If a fork must be speculative, trigger it from a plain function invoked outside the reactive flush.
- Defer fork creation with queueMicrotask when in doubt about the current batch state.
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
- fork_discarded
- hydratable_missing_but_required
- effect_in_unowned_derived
- effect_orphan
- effect_pending_outside_reaction
AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12).
Data as JSON: /api/errors/897ddb96d47cbb53.
Report an issue: GitHub.