Your sv migrate
finished running and now your app won't start. Welcome to migration hell. Here's the systematic approach I use to unfuck broken migrations, starting with the most common failures.
Step 1: Find Your Broken Shit
First thing - don't panic and start randomly fixing stuff. Get organized about what's actually broken:
## Find all the homework the migration tool left you
grep -r \"@migration\" src/
## Check for obvious build failures
npm run build 2>&1 | grep -E \"(error|ERROR)\"
## See what TypeScript is bitching about
npx tsc --noEmit
This gives you three categories of problems:
- @migration comments - stuff the tool couldn't figure out
- Build failures - broken imports, dependency issues, config problems
- TypeScript errors - type mismatches from the component signature changes
Step 2: Fix Build Issues First (Before You Touch Components)
Don't waste time debugging components if your build is broken. Common build failures after migration:
Dependency version conflicts:
npm ls | grep UNMET
## Usually some library that expects Svelte 4
Package.json dependency hell:
The migration tool sometimes fucks up your versions. Check your package.json
- if you see stuff like \"svelte\": \"^5.0.0\"
but other packages pinned to old versions, you're gonna have problems.
Quick fix for most dependency issues:
rm package-lock.json node_modules -rf
npm install
If that doesn't work, you probably have a library that doesn't support Svelte 5 yet. Check the compatibility discussions, the framework compatibility tracker, or find an alternative.
Import errors:
Module not found: Error: Can't resolve 'svelte/internal'
This usually means you have old imports that didn't get migrated. The migration tool sometimes misses custom imports. Search your codebase:
grep -r \"svelte/internal\" src/
grep -r \"svelte/store\" src/ # sometimes breaks too
For detailed guidance on these import changes, see the official migration patterns and large application upgrade experiences.
Step 3: TypeScript Errors (The Migration Changed Component Types)
Svelte 5's TypeScript integration is stricter than Svelte 4. Common errors after migration:
Component props type errors:
// Error: Type '{ name: string }' is not assignable to type 'ComponentProps<MyComponent>'
This happens because component prop types changed from class-based to function-based. The fix depends on how you were typing props before.
Old Svelte 4 pattern:
// This breaks in Svelte 5
export interface Props {
name: string;
}
New Svelte 5 pattern:
// This works
interface Props {
name: string;
}
let { name }: Props = $props();
Dynamic component type errors:
// Error: ComponentType is deprecated
<svelte:component this={Component} />
The migration tool usually handles this but sometimes fucks it up. The new pattern:
// Import the new type
import type { Component } from 'svelte';
// Use it properly
<svelte:component this={Component as Component} />
Step 4: Runtime Errors (The Sneaky Shit)
Build passes, TypeScript is happy, but your app crashes at runtime. These are the worst because they're hard to debug.
Rune errors:
Error: Cannot read properties of undefined (reading '$state')
This usually means you have runes outside of component context. The migration tool sometimes moves $state
calls to weird places.
Reactivity errors:
Error: Maximum call stack size exceeded
This is usually a circular dependency in your reactive statements. The migration tool sometimes creates infinite loops when converting complex $:
patterns to $effect()
.
Finding the source:
## Look for suspicious $effect patterns
grep -A 5 -B 5 \"\$effect\" src/
## Check for circular dependencies
grep -r \"\$state.*\$derived\" src/
Step 5: Testing Failures (Because Of Course They Break Too)
Component tests often break after migration, even when the components work fine in the browser.
Common test failures:
Error: Cannot find module 'svelte/internal'
TypeError: component.$$set is not a function
This happens because test libraries sometimes lag behind Svelte versions. Solutions:
Update your testing library:
npm install @testing-library/svelte@latest
Or switch to the new browser-based testing:
npm install vitest-browser-svelte
The new browser testing approach actually works better with Svelte 5 runes because it tests in real browsers instead of jsdom. For detailed migration guides, see migrating from testing-library and the complete testing migration guide.
The Nuclear Option (When Everything's Still Broken)
If you're hours into debugging and nothing works:
## Back to square one
git checkout . && git clean -fd
## Try component-by-component migration
npx sv migrate --help # check for individual file options
Or migrate individual components using the VS Code extension's "Migrate Component" command. This lets you see exactly what changes before committing. For complex applications, consider the incremental migration approach used by production teams.
Pro Tips from Multiple Migrations
Migrate on a branch, always. I've seen people YOLO this on main and then spend 3 days rolling back.
Test incrementally. Don't migrate 50 components and then wonder what broke. Migrate 5, test, commit, repeat.
Check the browser console immediately. Lots of migration issues show up as console warnings before they become real errors.
Don't ignore deprecation warnings. They're telling you what will break in the next version.
The migration tool handles the mechanical stuff, but it can't read your mind about complex patterns. Plan for manual debugging time - it's not the tool's fault, it's just the reality of major version upgrades.