sveltejs/svelte · warning · MigrationError

Can't migrate code with ${illegal_specifiers.join(' and ')}.

Error message

Can't migrate code with ${illegal_specifiers.join(' and ')}. Please migrate by hand.

What it means

Thrown by the migrate codemod when a `<script>` import statement contains specifiers the automigrator cannot safely rewrite or drop (tracked in `illegal_specifiers`). The remaining specifiers are joined into the message. It is caught by the migrate entry point and surfaced as a `<!-- @migration-task -->` comment in the returned source.

Source

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

							state.str.original.indexOf(',', specifier.end) !== -1 &&
							state.str.original.indexOf(',', specifier.end) <
								state.str.original.indexOf('}', specifier.end)
								? state.str.original.indexOf(',', specifier.end) + 1
								: specifier.end
						);
						while (state.str.original[end].trim() === '') end++;
						state.str.remove(/** @type {number} */ (specifier.start), end);
						removed_specifiers++;
						continue;
					}
					illegal_specifiers.push(specifier.imported.name);
				}
			}
			if (removed_specifiers === node.specifiers.length) {
				state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end));
			}
			if (illegal_specifiers.length > 0) {
				throw new MigrationError(
					`Can't migrate code with ${illegal_specifiers.join(' and ')}. Please migrate by hand.`
				);
			}
		}
	},
	ExportNamedDeclaration(node, { state, next }) {
		if (node.declaration) {
			next();
			return;
		}

		let count_removed = 0;
		for (const specifier of node.specifiers) {
			if (specifier.local.type !== 'Identifier') continue;

			const binding = state.scope.get(specifier.local.name);
			if (binding?.kind === 'bindable_prop') {
				state.str.remove(

View on GitHub (pinned to 20b341f100)

Solutions

  1. Read the named specifiers in the error and manually rewrite that import in the component, then re-run migrate.
  2. Move the offending import into a plain `.js`/`.ts` module instead of a `<script context="module">` block.
  3. Migrate the affected file by hand and exclude it from the batch run.

Example fix

// before
<script context="module">
  import { onMount, afterUpdate } from 'svelte';
</script>

// after (keep only what still applies; afterUpdate has no runes equivalent)
<script>
  import { onMount } from 'svelte';
</script>
Defensive patterns

Strategy: validation

Validate before calling

// Before migrating, scan module scripts for imports the codemod rejects.
function riskyModuleImports(source) {
  const matches = source.match(/<script\s+context=["']module["'][\s\S]*?<\/script>/g) || [];
  // flag re-exports of svelte lifecycle hooks or legacy helpers
  return matches.some(s => /import\s*\{[^}]*(onMount|afterUpdate|beforeUpdate|onDestroy)/.test(s));
}

Try / catch

const { code } = migrate({ filename, source });
if (/illegal|cannot be automatically migrated/i.test(code) && code.startsWith('<!-- @migration-task')) {
  // open the file and rewrite the flagged import by hand
}

Prevention

When it happens

Trigger: Running `migrate()` on a component whose `<script context="module">` or instance script imports symbols that the Svelte 4→5 transform treats as illegal (typically lifecycle/hook re-exports or specifiers tied to APIs removed in runes mode). The visitor collects offending `specifier.imported.name` entries and throws once the import node is processed.

Common situations: Components that re-export Svelte 4 lifecycle functions (`onMount`, `afterUpdate`, etc.) from `svelte` in a module script, or that import helpers used only by legacy patterns the codemod rewrites away. Most often seen in shared utility/component libraries.

Related errors


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