sveltejs/svelte · warning · MigrationError

This migration would change the name of a slot (${name} to $

Error message

This migration would change the name of a slot (${name} to ${new_name}) making the component unusable

What it means

Same slot-rename guard as error 7, but for the `$$slots` object access path (legacy programmatic slot declaration) rather than `<slot name=...>` markup. Triggered when `state.scope.generate(name)` cannot return the original slot name because it is already in scope, and renaming would break consumers.

Source

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

	} else if (node.name === '$$restProps' && state.analysis.uses_rest_props) {
		state.str.update(
			/** @type {number} */ (node.start),
			/** @type {number} */ (node.end),
			state.names.rest
		);
	} else if (node.name === '$$slots' && state.analysis.uses_slots) {
		if (parent?.type === 'MemberExpression') {
			if (state.analysis.custom_element) return;

			let name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name;
			let slot_name = name;
			const existing_prop = state.props.find((prop) => prop.slot_name === name);
			if (existing_prop) {
				name = existing_prop.local;
			} else if (name !== 'default') {
				let new_name = state.scope.generate(name);
				if (new_name !== name) {
					throw new MigrationError(
						`This migration would change the name of a slot (${name} to ${new_name}) making the component unusable`
					);
				}
			}

			name = name === 'default' ? 'children' : name;

			if (!existing_prop) {
				state.props.push({
					local: name,
					exported: name,
					init: '',
					bindable: false,
					optional: true,
					slot_name,
					// if it's the first time we encounter this slot
					// we start with any and delegate to when the slot
					// is actually rendered (it might not happen in that case)

View on GitHub (pinned to 20b341f100)

Solutions

  1. Rename the in-scope identifier that collides with the slot name and re-run migrate.
  2. Convert the `$$slots` usage to explicit snippet props by hand (`let { header } = $props()` then `{@render header?.()}`).
  3. Rename the slot (and all consumers) before migrating so the generated name is stable.

Example fix

// before
<script>
  let header = something();
  if ($$slots.header) { /* ... */ }
</script>

// after (manual)
<script>
  let { header } = $props();
  if (header) { /* ... */ }
</script>
Defensive patterns

Strategy: validation

Validate before calling

// Detect $$slots member access whose names collide with in-scope identifiers.
function slotsAccessCollisions(source) {
  const names = [...source.matchAll(/\$\$slots\.(\w+)/g)].map(m => m[1]);
  const idents = [...source.matchAll(/\b(?:let|const|var|function|import)\s+([\w$]+)/g)].map(m => m[1]);
  return names.filter(n => idents.includes(n));
}

Try / catch

const { code } = migrate({ filename, source });
if (code.startsWith('<!-- @migration-task') && /migration would change the name of a slot/i.test(code)) {
  // hand-migrate: `let { slotName } = $props()` and `{@render slotName?.()}`
}

Prevention

When it happens

Trigger: Running `migrate()` on a Svelte 4 component that reads `$$slots.foo` (programmatic slot access) where `foo` is taken in scope, so `scope.generate(name)` deduplicates it. The check fires only when `state.analysis.uses_slots` is true and the parent is a `MemberExpression`.

Common situations: Components that introspect slots dynamically via `$$slots`, e.g. conditional slot rendering using `if ($$slots.header)`. Common in framework/layout components that adapt to which slots the consumer provides.

Related errors


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