Skip to content

Commit ee8066f

Browse files
fix: print useful errors when subscribing to stores during SSR (#8960)
* print useful errors when subscribing to stores during SSR * changeset --------- Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
1 parent 2855027 commit ee8066f

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

.changeset/large-toes-fetch.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: print useful error when subscribing to SvelteKit's stores at the wrong time during SSR

packages/kit/src/runtime/app/stores.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,23 @@ export const getStores = () => {
2323
export const page = {
2424
/** @param {(value: any) => void} fn */
2525
subscribe(fn) {
26-
const store = getStores().page;
26+
const store = __SVELTEKIT_DEV__ ? get_store('page') : getStores().page;
2727
return store.subscribe(fn);
2828
}
2929
};
3030

3131
/** @type {typeof import('$app/stores').navigating} */
3232
export const navigating = {
3333
subscribe(fn) {
34-
const store = getStores().navigating;
34+
const store = __SVELTEKIT_DEV__ ? get_store('navigating') : getStores().navigating;
3535
return store.subscribe(fn);
3636
}
3737
};
3838

3939
/** @type {typeof import('$app/stores').updated} */
4040
export const updated = {
4141
subscribe(fn) {
42-
const store = getStores().updated;
42+
const store = __SVELTEKIT_DEV__ ? get_store('updated') : getStores().updated;
4343

4444
if (browser) {
4545
updated.check = store.check;
@@ -55,3 +55,18 @@ export const updated = {
5555
);
5656
}
5757
};
58+
59+
/**
60+
* @template {keyof ReturnType<typeof getStores>} Name
61+
* @param {Name} name
62+
* @returns {ReturnType<typeof getStores>[Name]}
63+
*/
64+
function get_store(name) {
65+
try {
66+
return getStores()[name];
67+
} catch (e) {
68+
throw new Error(
69+
`Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.`
70+
);
71+
}
72+
}

packages/kit/types/ambient.d.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,22 @@ declare module '$app/stores' {
292292

293293
/**
294294
* A readable store whose value contains page data.
295+
*
296+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
295297
*/
296298
export const page: Readable<Page>;
297299
/**
298300
* A readable store.
299301
* When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties.
300302
* When navigating finishes, its value reverts to `null`.
303+
*
304+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
301305
*/
302306
export const navigating: Readable<Navigation | null>;
303307
/**
304-
* A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
308+
* A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling.
309+
*
310+
* On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time.
305311
*/
306312
export const updated: Readable<boolean> & { check(): Promise<boolean> };
307313

0 commit comments

Comments
 (0)