sveltejs/svelte · error · Error

rune_outside_svelte

rune_outside_svelte

Error message

rune_outside_svelte
The `${rune}` rune is only available inside `.svelte` and `.svelte.js/ts` files
https://svelte.dev/e/rune_outside_svelte

What it means

Thrown at index-client.js:29 via a global getter trap installed by throw_rune_error(). Outside a .svelte, .svelte.js, or .svelte.ts file the compiler never rewrites rune calls ($state, $effect, $derived, $inspect, $props, $bindable) into runtime APIs; instead a global getter is installed that throws this error so misuse fails loudly rather than silently being treated as a plain identifier.

Solutions

  1. Rename the file to .svelte.js or .svelte.ts so the compiler processes the runes.
  2. If the file must stay plain .js, do not use runes — pass reactive values in/out via function parameters and return values.
  3. Move the runes-using code into a .svelte component or .svelte.js module.

Example fix

// before — utils.js (plain)
export const count = $state(0); // throws

// after — rename to utils.svelte.js
export const count = $state(0); // compiler rewrites to runtime API
Defensive patterns

Strategy: validation

Validate before calling

// Use runes only in .svelte, .svelte.js, or .svelte.ts files.
// Check file extension before writing runes:
import path from 'node:path';
function canUseRunes(file) {
  return /\.svelte(\.js|\.ts)?$/.test(path.extname(file));
}

Prevention

When it happens

Trigger: Writing `$state(0)` or any other rune in a plain .js / .ts / .mjs file. Because the compiler only processes .svelte* files, the rune is left as-is, resolves to the trapped global, and throws on access.

Common situations: Extracting reactive logic into a utility and forgetting to rename the file to .svelte.js; copy-pasting runes code into a plain module; importing a runes-using helper from a non-svelte file that was renamed.

Related errors


AI-assisted analysis of sveltejs/svelte@20b341f100 (2026-08-12). Data as JSON: /api/errors/21c9c94fc52f1cbf. Report an issue: GitHub.

Appendix: source

Thrown at packages/svelte/src/internal/client/errors.js:428

	} else {
		throw new Error(`https://svelte.dev/e/props_rest_readonly`);
	}
}

/**
 * The `%rune%` rune is only available inside `.svelte` and `.svelte.js/ts` files
 * @param {string} rune
 * @returns {never}
 */
export function rune_outside_svelte(rune) {
	if (DEV) {
		const error = new Error(`rune_outside_svelte\nThe \`${rune}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files\nhttps://svelte.dev/e/rune_outside_svelte`);

		error.name = 'Svelte error';

		throw error;
	} else {
		throw new Error(`https://svelte.dev/e/rune_outside_svelte`);
	}
}

/**
 * `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`);
	}
}

View on GitHub (pinned to 20b341f100)