diff --git a/.changeset/spotty-lobsters-smell.md b/.changeset/spotty-lobsters-smell.md
new file mode 100644
index 000000000000..3ae71ebe4848
--- /dev/null
+++ b/.changeset/spotty-lobsters-smell.md
@@ -0,0 +1,5 @@
+---
+"@sveltejs/kit": patch
+---
+
+fix: redirect loop after invalidate
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index 5f251a07362f..7c912eca69bf 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -332,7 +332,12 @@ async function _invalidate() {
if (!navigation_result || nav_token !== token) return;
if (navigation_result.type === 'redirect') {
- return _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token);
+ return _goto(
+ new URL(navigation_result.location, current.url).href,
+ { replaceState: true },
+ 1,
+ nav_token
+ );
}
if (navigation_result.props.page) {
@@ -1336,7 +1341,12 @@ async function navigate({
route: { id: null }
});
} else {
- _goto(new URL(navigation_result.location, url).href, {}, redirect_count + 1, nav_token);
+ _goto(
+ new URL(navigation_result.location, url).href,
+ { replaceState: replace_state },
+ redirect_count + 1,
+ nav_token
+ );
return false;
}
} else if (/** @type {number} */ (navigation_result.props.page.status) >= 400) {
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+layout.server.js b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+layout.server.js
new file mode 100644
index 000000000000..6e7037b6d28c
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+layout.server.js
@@ -0,0 +1,5 @@
+export async function load({ cookies }) {
+ return {
+ loggedIn: cookies.get('logged_in') === '1'
+ };
+}
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+page.svelte b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+page.svelte
new file mode 100644
index 000000000000..e00b21de0f86
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/+page.svelte
@@ -0,0 +1,2 @@
+
App with authorization
+ enter
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.js b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.js
new file mode 100644
index 000000000000..db2614906577
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.js
@@ -0,0 +1,10 @@
+import { redirect } from '@sveltejs/kit';
+
+export async function load({ parent }) {
+ const { loggedIn } = await parent();
+ if (!loggedIn) {
+ redirect(302, '/redirect/app-with-auth/signin');
+ }
+
+ return {};
+}
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.svelte b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.svelte
new file mode 100644
index 000000000000..a594977e0be9
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/main/+page.svelte
@@ -0,0 +1 @@
+main
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.js b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.js
new file mode 100644
index 000000000000..785dd85a2090
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.js
@@ -0,0 +1,10 @@
+import { redirect } from '@sveltejs/kit';
+
+export async function load({ parent }) {
+ const { loggedIn } = await parent();
+ if (loggedIn) {
+ redirect(302, '/redirect/app-with-auth/main');
+ }
+
+ return {};
+}
diff --git a/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.svelte b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.svelte
new file mode 100644
index 000000000000..6cf85daa8062
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/redirect/app-with-auth/signin/+page.svelte
@@ -0,0 +1,11 @@
+
+
+signin
+
diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js
index 2ecc4ba1c0da..de4ec3337197 100644
--- a/packages/kit/test/apps/basics/test/client.test.js
+++ b/packages/kit/test/apps/basics/test/client.test.js
@@ -623,6 +623,21 @@ test.describe('Invalidation', () => {
expect(next_layout_2).toBe(next_layout_1);
expect(next_page_2).not.toBe(next_page_1);
});
+
+ test('does not create new records in history for intermediate redirects', async ({
+ page,
+ clicknav
+ }) => {
+ await page.goto('/redirect/app-with-auth');
+ await clicknav("a[data-testid='enter']");
+ expect(await page.textContent('h1')).toContain('signin');
+
+ await clicknav("button[data-testid='login']");
+ expect(await page.textContent('h1')).toContain('main');
+
+ await page.evaluate(() => window.history.back());
+ expect(await page.textContent('h1')).toContain('App with authorization');
+ });
});
test.describe('data-sveltekit attributes', () => {