diff --git a/.changeset/olive-buses-shake.md b/.changeset/olive-buses-shake.md
new file mode 100644
index 000000000000..4d8d3b7ef1a0
--- /dev/null
+++ b/.changeset/olive-buses-shake.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: rerun load functions when the number of values of a tracked search parameter changes
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index a9a3950b45ff..58b88a7edb5e 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -1167,12 +1167,12 @@ function diff_search_params(old_url, new_url) {
const changed = new Set([...old_url.searchParams.keys(), ...new_url.searchParams.keys()]);
for (const key of changed) {
- const old_values = old_url.searchParams.getAll(key);
- const new_values = new_url.searchParams.getAll(key);
+ const old_values = old_url.searchParams.getAll(key).sort();
+ const new_values = new_url.searchParams.getAll(key).sort();
if (
- old_values.every((value) => new_values.includes(value)) &&
- new_values.every((value) => old_values.includes(value))
+ old_values.length === new_values.length &&
+ old_values.every((value, i) => value === new_values[i])
) {
changed.delete(key);
}
diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/search-params/universal/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/invalidation/search-params/universal/+page.svelte
index 4ec557e316f1..02867d8f32d6 100644
--- a/packages/kit/test/apps/basics/src/routes/load/invalidation/search-params/universal/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/search-params/universal/+page.svelte
@@ -6,3 +6,4 @@
Change tracked parameter
Change untracked parameter
+Duplicate tracked parameter
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index 143244dcba84..4731f9200d67 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -525,6 +525,16 @@ test.describe('Invalidation', () => {
expect(await page.textContent('span')).toBe('count: 1');
});
+ test('load function re-runs when the number of values of a tracked searchParam changes', async ({
+ page,
+ clicknav
+ }) => {
+ await page.goto('/load/invalidation/search-params/universal?a=0');
+ expect(await page.textContent('span')).toBe('count: 0');
+ await clicknav('[data-id="duplicate"]');
+ expect(await page.textContent('span')).toBe('count: 1');
+ });
+
test('server-only load functions are re-run following forced invalidation', async ({
page,
request,