diff --git a/documentation/docs/98-reference/.generated/client-errors.md b/documentation/docs/98-reference/.generated/client-errors.md
index 32348bb781..b9268636b2 100644
--- a/documentation/docs/98-reference/.generated/client-errors.md
+++ b/documentation/docs/98-reference/.generated/client-errors.md
@@ -110,6 +110,12 @@ Rest element properties of `$props()` such as `%property%` are readonly
The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
```
+### set_context_after_init
+
+```
+`setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression
+```
+
### state_descriptors_fixed
```
diff --git a/packages/svelte/messages/client-errors/errors.md b/packages/svelte/messages/client-errors/errors.md
index c4e68f8fee..8748bf8978 100644
--- a/packages/svelte/messages/client-errors/errors.md
+++ b/packages/svelte/messages/client-errors/errors.md
@@ -72,6 +72,10 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long
> The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
+## set_context_after_init
+
+> `setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression
+
## state_descriptors_fixed
> Property descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.
diff --git a/packages/svelte/src/internal/client/context.js b/packages/svelte/src/internal/client/context.js
index c0c4f5fda9..f326f3a0b7 100644
--- a/packages/svelte/src/internal/client/context.js
+++ b/packages/svelte/src/internal/client/context.js
@@ -2,6 +2,7 @@
import { DEV } from 'esm-env';
import { lifecycle_outside_component } from '../shared/errors.js';
+import * as e from './errors.js';
import { source } from './reactivity/sources.js';
import {
active_effect,
@@ -10,7 +11,7 @@ import {
set_active_reaction
} from './runtime.js';
import { effect, teardown } from './reactivity/effects.js';
-import { legacy_mode_flag } from '../flags/index.js';
+import { async_mode_flag, legacy_mode_flag } from '../flags/index.js';
/** @type {ComponentContext | null} */
export let component_context = null;
@@ -65,6 +66,13 @@ export function getContext(key) {
*/
export function setContext(key, context) {
const context_map = get_or_init_context_map('setContext');
+
+ if (async_mode_flag) {
+ if (/** @type {ComponentContext} */ (component_context).m) {
+ e.set_context_after_init();
+ }
+ }
+
context_map.set(key, context);
return context;
}
diff --git a/packages/svelte/src/internal/client/errors.js b/packages/svelte/src/internal/client/errors.js
index 429dd99da9..0209976b11 100644
--- a/packages/svelte/src/internal/client/errors.js
+++ b/packages/svelte/src/internal/client/errors.js
@@ -197,6 +197,21 @@ export function hydration_failed() {
}
}
+/**
+ * `setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression
+ * @returns {never}
+ */
+export function set_context_after_init() {
+ if (DEV) {
+ const error = new Error(`set_context_after_init\n\`setContext\` must be called when a component first initializes, not in a subsequent effect or after an \`await\` expression\nhttps://svelte.dev/e/set_context_after_init`);
+
+ error.name = 'Svelte error';
+ throw error;
+ } else {
+ throw new Error(`https://svelte.dev/e/set_context_after_init`);
+ }
+}
+
/**
* Could not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`
* @returns {never}
diff --git a/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/_config.js b/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/_config.js
new file mode 100644
index 0000000000..cc7c483667
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/_config.js
@@ -0,0 +1,11 @@
+import { flushSync } from 'svelte';
+import { test } from '../../test';
+
+export default test({
+ async test({ target, assert, logs }) {
+ const button = target.querySelector('button');
+
+ flushSync(() => button?.click());
+ assert.ok(logs[0].startsWith('set_context_after_init'));
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/main.svelte b/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/main.svelte
new file mode 100644
index 0000000000..40145c28da
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/set-context-after-mount/main.svelte
@@ -0,0 +1,19 @@
+
+
+