fix: prevent #each array key from blowing up on updates
#17723
#each array key from blowing up on updatesClosing issue
Describe the bug
https://svelte.dev/docs/svelte/each#Keyed-each-blocks
The key can be any object
So I tried using array as a key for #each block:
{#each things as thing ([thing.group, thing.id])}
Works fine when page loads, but when data changes, it throws error.
Had to convert to string in order to get it working:
{#each things as thing ([thing.group, thing.id].join('-')}
So either docs need updating, or #each needs fixing to support array keys
Reproduction
https://svelte.dev/playground/1db5362a3e974b209b11ae389758c93f?version=5.51.2
Click button, check browser console.
Logs
playground:output:5619 Uncaught TypeError: Cannot read properties of undefined (reading 'e')
at reconcile (playground:output:5619:54)
at commit (playground:output:5450:4)
at Batch.process (playground:output:1109:46)
at flush_effects (playground:output:1484:11)
at Batch.flush (playground:output:1244:5)
at Array.eval (playground:output:1417:13)
at run_all (playground:output:126:10)
at run_micro_tasks (playground:output:739:3)
at eval (playground:output:757:32)
System Info
System:
OS: macOS 26.3
CPU: (14) arm64 Apple M4 Pro
Memory: 439.02 MB / 24.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.10.0 - /Users/kieran/.local/share/mise/installs/node/24.10.0/bin/node
npm: 11.6.1 - /Users/kieran/.local/share/mise/installs/node/24.10.0/bin/npm
pnpm: 10.29.3 - /Users/kieran/.local/share/mise/installs/node/24.10.0/bin/pnpm
npmPackages:
svelte: 5.51.0 => 5.51.0
Severity
annoyance
Pull request
Fixes #17721
Keyed #each blocks accept any object, but array-literal keys (e.g. ([thing.group, thing.id])) could crash on updates because get_key was called multiple times per update, producing new array instances and causing internal Map lookups to miss. This change computes keys once per update, stores them in key_list, and reuses them throughout reconcile() (including the animation prepass), preventing the runtime error even though array-literal keys remain inherently unstable for identity across updates.
Before submitting the PR, please make sure you do the following
- It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- Prefix your PR title with
feat:,fix:,chore:, ordocs:. - This message body should clearly illustrate what problems it solves.
- Ideally, include a test that fails without this PR but passes with it.
- If this PR changes code within
packages/svelte/src, add a changeset (npx changeset).
Tests and linting
- Run the tests with
pnpm testand lint the project withpnpm lint
Info
🦋 Changeset detected
Latest commit: 09ca611
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 1 package
| Name | Type |
|---|---|
| svelte | Patch |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
In the issue, the user creates new keys on each run of #each which is the same as having no key at all. So such a fix makes no sense.
Rather, it should be a descriptive error that keys must be stable. But errors must not be thrown in reconcile. Maybe in the effect, in the first iteration and DEV checking that get_key(value, index) === get_key(value, index) will be enough.
Pro tip: You can prefix GitHub URLs of issues, PRs or discussions with svcl.dev/ to view them on this page! Also try it on a GitHub release ;)