From bd4c6396d6b4024b9cd2217ed44e963f9708602b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 16 Jul 2025 16:45:23 -0400 Subject: [PATCH] update effect_update_depth_exceeded docs --- .../98-reference/.generated/client-errors.md | 38 ++++++++++++++++++- .../svelte/messages/client-errors/errors.md | 38 ++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/documentation/docs/98-reference/.generated/client-errors.md b/documentation/docs/98-reference/.generated/client-errors.md index c7d6ec8ac9..7109f40e92 100644 --- a/documentation/docs/98-reference/.generated/client-errors.md +++ b/documentation/docs/98-reference/.generated/client-errors.md @@ -89,9 +89,45 @@ Effect cannot be created inside a `$derived` value that was not itself created i ### effect_update_depth_exceeded ``` -Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops +Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state ``` +If an effect updates some state that it also depends on, it will re-run, potentially in a loop: + +```js +let count = $state(0); + +$effect(() => { + // this both reads and writes `count`, + // so will run in an infinite loop + count += 1; +}); +``` + +(Svelte intervenes before this can crash your browser tab.) + +The same applies to array mutations, since these both read and write to the array: + +```js +let array = $state([]); + +$effect(() => { + array.push('hello'); +}); +``` + +Note that it's fine for an effect to re-run itself as long as it 'settles': + +```js +$effect(() => { + // this is okay, because sorting an already-sorted array + // won't result in a mutation + array.sort(); +}); +``` + +Often when encountering this issue, the value in question shouldn't be state (for example, if you are pushing to a `logs` array in an effect, make `logs` a normal array rather than `$state([])`). In the rare cases where you really _do_ need to write to state in an effect — [which you should avoid]($effect#When-not-to-use-$effect) — you can read the state with [untrack](svelte#untrack) to avoid adding it as a dependency. + ### flush_sync_in_effect ``` diff --git a/packages/svelte/messages/client-errors/errors.md b/packages/svelte/messages/client-errors/errors.md index 2ce25dbd53..391c529e85 100644 --- a/packages/svelte/messages/client-errors/errors.md +++ b/packages/svelte/messages/client-errors/errors.md @@ -60,7 +60,43 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long ## effect_update_depth_exceeded -> Maximum update depth exceeded. This can happen when a reactive block or effect repeatedly sets a new value. Svelte limits the number of nested updates to prevent infinite loops +> Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state + +If an effect updates some state that it also depends on, it will re-run, potentially in a loop: + +```js +let count = $state(0); + +$effect(() => { + // this both reads and writes `count`, + // so will run in an infinite loop + count += 1; +}); +``` + +(Svelte intervenes before this can crash your browser tab.) + +The same applies to array mutations, since these both read and write to the array: + +```js +let array = $state([]); + +$effect(() => { + array.push('hello'); +}); +``` + +Note that it's fine for an effect to re-run itself as long as it 'settles': + +```js +$effect(() => { + // this is okay, because sorting an already-sorted array + // won't result in a mutation + array.sort(); +}); +``` + +Often when encountering this issue, the value in question shouldn't be state (for example, if you are pushing to a `logs` array in an effect, make `logs` a normal array rather than `$state([])`). In the rare cases where you really _do_ need to write to state in an effect — [which you should avoid]($effect#When-not-to-use-$effect) — you can read the state with [untrack](svelte#untrack) to avoid adding it as a dependency. ## flush_sync_in_effect