sveltejs/svelte · warning · MigrationError

migrating this component would require adding a `$${rune}` r

Error message

migrating this component would require adding a `$${rune}` rune but there's already a variable named ${rune}.
     Rename the variable and try again or migrate by hand.

What it means

Thrown (as a `MigrationError`) by Svelte's Svelte 4 → 5 codemod when a component needs one of the runes `$derived`, `$props`, or `$bindable` injected, but the component's own scope already declares a user variable with that bare name (e.g. `let derived = ...`). Injecting the rune would shadow or collide with the variable, so the automigrator refuses rather than produce broken code. The migrate entry function catches it and emits the original source back with a `<!-- @migration-task -->` comment instead of crashing.

Source

Thrown at packages/svelte/src/compiler/migrate/index.js:280

			str.appendRight(insertion_point, `\n${indent}${legacy_import}`);
		}

		if (state.script_insertions.size > 0) {
			str.appendRight(
				insertion_point,
				`\n${indent}${[...state.script_insertions].join(`\n${indent}`)}`
			);
		}

		insertion_point = state.props_insertion_point;

		/**
		 * @param {"derived"|"props"|"bindable"} rune
		 */
		function check_rune_binding(rune) {
			const has_rune_binding = !!state.scope.get(rune);
			if (has_rune_binding) {
				throw new MigrationError(
					`migrating this component would require adding a \`$${rune}\` rune but there's already a variable named ${rune}.\n     Rename the variable and try again or migrate by hand.`
				);
			}
		}

		if (state.props.length > 0 || analysis.uses_rest_props || analysis.uses_props) {
			const has_many_props = state.props.length > 3;
			const newline_separator = `\n${indent}${indent}`;
			const props_separator = has_many_props ? newline_separator : ' ';
			let props = '';
			if (analysis.uses_props) {
				props = `...${state.names.props}`;
			} else {
				props = state.props
					.filter((prop) => !prop.type_only)
					.map((prop) => {
						let prop_str =
							prop.local === prop.exported ? prop.local : `${prop.exported}: ${prop.local}`;

View on GitHub (pinned to 20b341f100)

Solutions

  1. Rename the colliding variable in the source component (e.g. `let props` → `let forwardedProps`) and re-run the migrator.
  2. If you do not need the automigrator for that file, migrate it by hand and skip the codemod for it.
  3. Grep the component for `\b(props|derived|bindable)\b` declarations before running migrate to pre-empt the collision.

Example fix

// before
<script>
  export let derived;
  let derived = computed();
</script>

// after (rename, then migrate)
<script>
  let { derivedValue = computed() } = $props();
</script>
Defensive patterns

Strategy: validation

Validate before calling

// Before running migrate(), scan the component for rune-name collisions.
function hasRuneNameCollision(source) {
  return /\b(let|const|var)\s+(props|derived|bindable)\b/.test(source);
}
if (hasRuneNameCollision(componentSource)) {
  // rename before migrating
}

Try / catch

// migrate() never throws MigrationError — it returns code with a marker comment.
const { code } = migrate({ filename, source });
if (code.startsWith('<!-- @migration-task')) {
  // inspect the embedded message and finish migration by hand
}

Prevention

When it happens

Trigger: Running `npx sv migrate svelte-5` (or the programmatic `migrate()` export) on a component that (a) needs `$props`/`$derived`/`$bindable` generated and (b) contains a top-level `let derived`, `let props`, or `let bindable` declaration. The `check_rune_binding` helper looks up the rune name in `state.scope` and throws when the binding exists.

Common situations: Pre-existing variables named `props`, `derived`, or `bindable` in Svelte 4 components — `props` in particular is a common local alias for `$props`-style patterns or for forwarded prop bags. Migration succeeds for other components in the batch but stalls on these.

Related errors


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