sveltejs/svelte · error · Error

flush_sync_in_effect

flush_sync_in_effect

Error message

flush_sync_in_effect
Cannot use `flushSync` inside an effect
https://svelte.dev/e/flush_sync_in_effect

What it means

Thrown when flushSync() is called from inside a running effect. flushSync forces synchronous flush of pending updates; calling it from within an effect that is itself part of the flush cycle would re-enter the flusher and corrupt Svelte's internal batch state, so it is rejected.

Source

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

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

/**
 * Cannot use `flushSync` inside an effect
 * @returns {never}
 */
export function flush_sync_in_effect() {
	if (DEV) {
		const error = new Error(`flush_sync_in_effect\nCannot use \`flushSync\` inside an effect\nhttps://svelte.dev/e/flush_sync_in_effect`);

		error.name = 'Svelte error';

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

/**
 * Cannot commit a fork that was already discarded
 * @returns {never}
 */
export function fork_discarded() {
	if (DEV) {
		const error = new Error(`fork_discarded\nCannot commit a fork that was already discarded\nhttps://svelte.dev/e/fork_discarded`);

		error.name = 'Svelte error';

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

View on GitHub (pinned to 20b341f100)

Solutions

  1. Remove the flushSync call — by the time the effect runs, scheduling is already managed by Svelte; queue the work via a microtask or $effect instead.
  2. If you need to ensure updates are applied, use await tick() rather than flushSync.
  3. Move the flushSync call to an event handler or onMount where no effect is mid-flush.

Example fix

// before
import { flushSync } from 'svelte';
$effect(() => {
  flushSync(); // re-entrant flush
  measureNode();
});

// after
import { tick } from 'svelte';
$effect(() => {
  tick().then(() => measureNode());
});
Defensive patterns

Strategy: validation

Validate before calling

// Do not call flushSync inside an effect. Replace with tick():
import { tick } from 'svelte';
// $effect(() => { tick().then(() => measure()); });
// If you must flush synchronously, do it from an event handler, not an effect.

Prevention

When it happens

Trigger: Calling the imported flushSync from 'svelte' (or this lib) directly inside a $effect callback, an $effect.pre, or a function synchronously invoked from one while the effect is flushing. The guard detects re-entrant sync flushing.

Common situations: Calling flushSync to force DOM measurement inside an effect; wrapping test assertions in flushSync within a component effect; porting legacy afterUpdate code that used tick()/flush synchronously into a runes effect.

Related errors


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