\n ```\n\nDon't try to use both patterns in the same component - it confuses the reactivity system." } }, { "@type": "Question", "name": "Performance got worse after migration. Is this normal?", "acceptedAnswer": { "@type": "Answer", "text": "Sometimes, yes. The migration tool creates compatibility layers that can slow things down temporarily.\n\n**Check for these performance killers:**\n\n**Unnecessary compatibility imports:**\n```svelte\n\nimport { createEventDispatcher } from 'svelte';\nimport { tick } from 'svelte';\n```\n\n**Over-reactive effects:**\n```svelte\n\n$effect(() => {\n // Don't put everything in one huge effect\n handleUserChanges();\n handlePermissionChanges();\n handleDataChanges();\n});\n```\n\n**Fix:** Split into targeted effects:\n```svelte\n\n$effect(() => {\n handleUserChanges();\n});\n\n$effect(() => {\n handlePermissionChanges();\n});\n```" } }, { "@type": "Question", "name": "I'm getting \"hydration mismatch\" errors that didn't exist before", "acceptedAnswer": { "@type": "Answer", "text": "[SSR/hydration](https://svelte.dev/docs/kit/glossary#hydration) behavior changed slightly in Svelte 5. Usually this means client and server render different content.\n\n**Debug approach:**\n```bash\n# Check if it's a specific component\ngrep -r \"hydration\" src/\n\n# Look for conditional rendering that might differ between server/client\ngrep -r \"browser\\|document\\|window\" src/\n```\n\n**Common causes:**\n- Date/time rendering differences between server and client\n- User-specific content that renders differently\n- Browser-only APIs being called during SSR\n\n**Quick fix:** Use `{#if browser}` blocks for browser-only content:\n```svelte\n\n\n{#if browser}\n \n{/if}\n```" } }, { "@type": "Question", "name": "Components work in development but break in production", "acceptedAnswer": { "@type": "Answer", "text": "This usually means your build process isn't handling Svelte 5 correctly.\n\n**Check your build config:**\n1. Vite config might need updates for Svelte 5\n2. TypeScript config might be too strict for new patterns\n3. Your bundler might not understand rune syntax\n\n**Debug production issues:**\n```bash\n# Build locally and test\nnpm run build\nnpm run preview\n\n# Check build output for errors\nnpm run build 2>&1 | grep -E \"(error|ERROR|warning|WARNING)\"\n```\n\n**Common production-only issues:**\n- CSS gets stripped incorrectly\n- Dead code elimination removes needed imports\n- Minification breaks rune syntax" } }, { "@type": "Question", "name": "My VSCode extension is showing errors but the app works fine", "acceptedAnswer": { "@type": "Answer", "text": "The language server sometimes lags behind Svelte releases or gets confused by mixed syntax.\n\n**Fixes to try:**\n1. **Restart the language server:** Cmd/Ctrl+Shift+P → \"Svelte: Restart Language Server\"\n2. **Update the extension:** Make sure you have the [latest Svelte extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode)\n3. **Check your workspace settings:** Sometimes project-specific settings break things\n\n**If errors persist:**\n```bash\n# Check if it's a real TypeScript error\nnpx tsc --noEmit\n\n# vs just a language server issue\n```" } }, { "@type": "Question", "name": "I want to revert specific components but keep others migrated", "acceptedAnswer": { "@type": "Answer", "text": "You can mix Svelte 4 and 5 syntax in the same app, but there are gotchas.\n\n**Safe to mix:**\n- Components using old syntax in a Svelte 5 project\n- Stores remain as stores while some components use runes\n\n**Not safe to mix:**\n- Runes and reactive statements in the same component\n- Old and new event handling patterns in parent/child relationships\n\n**Reverting specific components:**\n```bash\n# Revert individual files\ngit checkout HEAD~1 -- src/components/problematic-component.svelte\n\n# Or use VS Code to undo specific changes\n```" } }, { "@type": "Question", "name": "Tests pass but end-to-end tests fail", "acceptedAnswer": { "@type": "Answer", "text": "E2E tests might be hitting timing differences or behavior changes that unit tests miss.\n\n**Common E2E issues after migration:**\n- Page load timing changed\n- Event handling timing is different\n- Animation/transition timing changed\n\n**Debug approach:**\n```bash\n# Add more explicit waits in your E2E tests\nawait page.waitForSelector('[data-testid=\"component-loaded\"]');\n\n# Instead of assuming timing\nawait page.waitForTimeout(1000); // bad\n```\n\n**Better E2E patterns for Svelte 5:**\n- Wait for specific elements, not time\n- Test user interactions, not implementation details\n- Use data attributes for test targeting" } }, { "@type": "Question", "name": "My migration worked but deployment failed", "acceptedAnswer": { "@type": "Answer", "text": "Deployment environments sometimes have different requirements than development.\n\n**Check these deployment-specific issues:**\n1. **Node version:** Make sure production uses Node 16+\n2. **Build environment:** CI might need dependency updates\n3. **Environment variables:** Svelte 5 might handle env vars differently\n\n**Debug deployment:**\n```bash\n# Test your production build locally\nNODE_ENV=production npm run build\nnpm run preview\n\n# Check if it's environment-specific\nnpm run build -- --mode production\n```" } }, { "@type": "Question", "name": "Everything works but bundle size got huge", "acceptedAnswer": { "@type": "Answer", "text": "The migration tool sometimes adds unnecessary compatibility imports and doesn't clean up dead code.\n\n**Find bloat:**\n```bash\n# Analyze your bundle\nnpm run build -- --analyze\n\n# Or use a bundle analyzer\nnpx vite-bundle-analyzer dist/\n```\n\n**Common bloat sources:**\n- Unused compatibility imports\n- Old stores that could be converted to runes\n- Duplicate dependencies (old + new versions)\n\n**Cleanup:**\n```bash\n# Remove unused imports\nnpx depcheck\n\n# Update all dependencies to latest compatible versions\nnpx npm-check-updates -u\n```\n\n**Remember:** Migration success isn't just \"it compiles\" - it's \"it works the same way with better performance.\" Budget time for post-migration optimization, especially for production apps." } } ] }
Currently viewing the human version
Switch to AI version

The Post-Migration Debugging Workflow (What to Do When Everything's Fucked)

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:

  1. @migration comments - stuff the tool couldn't figure out
  2. Build failures - broken imports, dependency issues, config problems
  3. TypeScript errors - type mismatches from the component signature changes

Debugging Workflow

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.

Common Migration Failures (And How to Actually Fix Them)

Q

My app won't even build after migration. What the fuck?

A

First check if it's a dependency issue:

npm ls | grep -E \"(UNMET|missing)\"

If you see missing dependencies, you've got library compatibility problems. The migration updates Svelte to v5 but doesn't check if your other packages support it.

Quick fix:

rm package-lock.json node_modules -rf && npm install

If that doesn't work, check which packages are bitching:

npm run build 2>&1 | head -20

Look for error messages like Module not found or Cannot resolve. Usually it's a UI library that needs updating or doesn't support Svelte 5 yet.

Q

I'm getting "Cannot read properties of undefined (reading '$state')" errors

A

This means you have runes running outside component context. The migration tool sometimes moves $state calls to weird places.

Find the problem:

grep -n \"\$state|\$derived|\$effect\" src/**/*.js src/**/*.ts

Look for runes in:

  • Utility functions outside components
  • Store files that got converted incorrectly
  • Helper modules that aren't actually Svelte files

Fix: Move the runes back inside component context or use proper stores for shared state.

Q

TypeScript is throwing errors about component types that didn't exist before

A

Svelte 5's TypeScript integration is stricter. The most common error:

Type '{ prop: string }' is not assignable to type 'ComponentProps<MyComponent>'

This happens because component prop types changed from class-based to function-based.

If you were using this pattern:

// Old Svelte 4 - breaks
export interface Props {
  name: string;
}

Change to this:

// New Svelte 5 - works
interface Props {
  name: string;
}

let { name }: Props = $props();
Q

My tests are failing with "component.$$set is not a function"

A

Your testing library doesn't understand Svelte 5 components yet. Two options:

Option 1: Update to latest testing library:

npm install @testing-library/svelte@latest

Option 2: Switch to browser-based testing (recommended):

npm install vitest-browser-svelte

The browser testing approach actually works better with runes because it tests in real browsers instead of mocked environments.

Q

What does "@migration: This reactive statement is too complex" actually mean?

A

It means you have a $: statement that does multiple things and the tool gave up trying to convert it. Example:

<!-- This confuses the migration tool -->
$: {
  if (condition) {
    doSomething();
    updateMultipleThings(a, b, c);
    dispatchEvent();
  }
}

Fix: Convert to $effect() manually:

$effect(() => {
  if (condition) {
    doSomething();
    updateMultipleThings(a, b, c);
    dispatchEvent();
  }
});
Q

My custom stores broke after migration. How do I fix them?

A

If your stores use complex reactive patterns, the migration might have fucked up the dependencies.

Check for this pattern:

// If migration converted your store file to use runes
const myStore = $state(initialValue); // This breaks outside components

Fix: Keep stores as stores, don't convert them to runes:

// Keep this as a proper store
import { writable } from 'svelte/store';
const myStore = writable(initialValue);

Runes are for component state. Stores are for shared state between components.

Q

I'm getting infinite loops/maximum call stack errors

A

The migration tool sometimes creates circular dependencies when converting complex $: patterns.

Find the problem:

grep -A 3 -B 3 \"\$effect\" src/ | grep -E \"(\$state|\$derived)\"

Look for patterns where $effect modifies state that triggers the same $effect.

Common broken pattern:

let count = $state(0);

$effect(() => {
  count = count + 1; // Infinite loop!
});

Fix: Use $effect.pre() for pre-update effects or restructure your logic to avoid circular dependencies.

Q

Dynamic components are broken with "ComponentType is deprecated" errors

A

The migration sometimes fucks up dynamic component typing.

If you have:

<svelte:component this={Component} />

And getting type errors, fix the import:

import type { Component } from 'svelte';

<svelte:component this={Component as Component} />

The new Component type is different from the old ComponentType.

Q

Form binding stopped working after migration

A

Two-way binding syntax changed slightly in some edge cases.

If you have binding errors, check for:

<!-- This might break -->
<input bind:value={someComplexExpression.prop} />

Convert to:

<!-- This works -->
<input bind:value={simpleVariable} />

Complex binding expressions sometimes need to be simplified for Svelte 5.

Q

My animations/transitions are acting weird

A

Transition behavior changed slightly in Svelte 5. If animations are broken:

  1. Check the browser console for deprecation warnings
  2. Look for transition props that got converted incorrectly
  3. Some transition libraries need updates for Svelte 5 compatibility

Most animation issues resolve themselves after updating animation libraries to Svelte 5 compatible versions.

Fixing Specific Broken Patterns (The Shit That Always Breaks)

After debugging dozens of migrations, certain patterns break consistently. Here are the specific code patterns that trip up the migration tool and exactly how to fix them.

Complex Reactive Statements (The Migration Tool's Nemesis)

The tool handles simple $: doubled = count * 2 fine, but anything more complex usually gets an @migration comment.

Pattern that breaks:

<!-- Migration tool gives up here -->
$: {
  if (user?.isAuthenticated && permissions.length > 0) {
    const allowedActions = permissions.filter(p => p.active);
    if (allowedActions.some(a => a.type === 'admin')) {
      showAdminUI = true;
      loadAdminData();
    } else {
      showAdminUI = false;
      clearAdminData();
    }
  }
}

How to fix it manually:

<!-- Convert to $effect with proper dependencies -->
$effect(() => {
  if (user?.isAuthenticated && permissions.length > 0) {
    const allowedActions = permissions.filter(p => p.active);
    if (allowedActions.some(a => a.type === 'admin')) {
      showAdminUI = true;
      loadAdminData();
    }
    else {
      showAdminUI = false;
      clearAdminData();
    }
  }
});

Pro tip: The migration tool bails when it sees multiple statements, function calls, or complex conditionals. Break these into smaller, simpler reactive statements when possible. For detailed guidance on reactive statement conversion, see the runes introduction guide and $effect documentation.

Store Integration Patterns (Always Gets Fucked)

If your components have complex store interactions, migration often breaks the patterns.

Pattern that breaks:

<!-- Old Svelte 4 pattern -->
<script>
  import { myStore } from './stores.js';

  $: if ($myStore.user) {
    // Complex logic that depends on store value
    updateSomething($myStore.user.id);
    // Migration tool can't figure this out
  }
</script>

How to fix it:

<!-- New Svelte 5 pattern -->
<script>
  import { myStore } from './stores.js';

  // Subscribe properly to stores in Svelte 5
  let storeValue = $state();

  $effect(() => {
    return myStore.subscribe(value => {
      storeValue = value;
    });
  });

  $effect(() => {
    if (storeValue?.user) {
      updateSomething(storeValue.user.id);
    }
  });
</script>

Alternative approach: Keep using the $ syntax for simple store subscriptions - it still works in Svelte 5. For advanced store patterns with runes, see Svelte 5 store patterns and global state management strategies:

<script>
  import { myStore } from './stores.js';

  // This still works fine
  $effect(() => {
    if ($myStore.user) {
      updateSomething($myStore.user.id);
    }
  });
</script>

Component Communication Patterns (Event Dispatchers Break)

`createEventDispatcher` patterns often get mangled by migration.

Pattern that breaks:

<!-- Old pattern that confuses migration -->
<script>
  import { createEventDispatcher } from 'svelte';

  const dispatch = createEventDispatcher();

  function handleComplexEvent(data) {
    // Migration tool struggles with complex dispatch patterns
    if (data.isValid) {
      dispatch('success', {
        result: processData(data),
        timestamp: Date.now()
      });
    } else {
      dispatch('error', {
        message: 'Invalid data',
        details: data.errors
      });
    }
  }
</script>

Fixed pattern:

<!-- Convert to callback props (preferred in Svelte 5) -->
<script>
  let { onSuccess, onError } = $props();

  function handleComplexEvent(data) {
    if (data.isValid) {
      onSuccess?.({
        result: processData(data),
        timestamp: Date.now()
      });
    } else {
      onError?.({
        message: 'Invalid data',
        details: data.errors
      });
    }
  }
</script>

Lifecycle Hook Dependencies (Gets Messy)

When your onMount or lifecycle hooks have complex dependencies, migration often breaks the timing. For comprehensive lifecycle migration patterns, see the official migration guide and practical upgrade experiences.

Pattern that breaks:

<!-- Migration sometimes fucks up the timing -->
<script>
  import { onMount } from 'svelte';

  let data = [];
  let loading = true;

  onMount(async () => {
    // Complex async patterns confuse migration
    if (user?.authenticated && permissions.includes('read')) {
      try {
        data = await fetchUserData(user.id);
        loading = false;
      } catch (error) {
        handleError(error);
        loading = false;
      }
    }
  });
</script>

Fixed pattern:

<!-- Use $effect with proper dependencies -->
<script>
  let data = $state([]);
  let loading = $state(true);

  $effect(() => {
    if (user?.authenticated && permissions.includes('read')) {
      loading = true;

      fetchUserData(user.id)
        .then(result => {
          data = result;
          loading = false;
        })
        .catch(error => {
          handleError(error);
          loading = false;
        });
    }
  });
</script>

Dynamic Component Patterns (TypeScript Nightmare)

Dynamic components with complex props often break during migration. For detailed TypeScript migration guidance, see the Svelte 5 TypeScript documentation and component type migration examples.

Pattern that breaks:

<!-- TypeScript gets confused after migration -->
<script lang=\"ts\">
  import type { ComponentType } from 'svelte';

  // This type reference breaks in Svelte 5
  export let dynamicComponent: ComponentType;
  export let componentProps: Record<string, any>;
</script>

<svelte:component this={dynamicComponent} {...componentProps} />

Fixed pattern:

<!-- Use new Svelte 5 component typing -->
<script lang=\"ts\">
  import type { Component } from 'svelte';

  // New type system
  let {
    dynamicComponent,
    componentProps
  }: {
    dynamicComponent: Component;
    componentProps: Record<string, any>
  } = $props();
</script>

<svelte:component this={dynamicComponent} {...componentProps} />

Binding Edge Cases (Two-Way Binding Breaks)

Complex binding expressions often break subtly after migration. For detailed binding patterns and $derived usage, see the comprehensive examples and edge cases covered in migration discussions.

Pattern that breaks:

<!-- Complex binding that breaks -->
<script>
  let formData = { user: { profile: { name: '' } } };
</script>

<!-- This deep binding sometimes breaks -->
<input bind:value={formData.user.profile.name} />

Fixed pattern:

<!-- Flatten binding or use derived values -->
<script>
  let formData = $state({ user: { profile: { name: '' } } });

  // Create a derived binding
  let profileName = $derived.by(() => ({
    get value() { return formData.user.profile.name; },
    set value(newName) { formData.user.profile.name = newName; }
  }));
</script>

<input bind:value={profileName.value} />

The \"Everything Works But Tests Fail\" Pattern

Your components work in the browser but tests break because testing libraries don't understand the new patterns. For comprehensive testing migration strategies, see the testing library compatibility tracker and modern testing approaches.

What breaks in tests:

// Old test pattern that breaks
import { render } from '@testing-library/svelte';
import Component from './Component.svelte';

// This fails with Svelte 5 runes
const { component } = render(Component, { props: { name: 'test' } });
component.$set({ name: 'updated' }); // $$set doesn't exist anymore

Fixed test pattern:

// New test approach for Svelte 5
import { render } from '@testing-library/svelte';
import Component from './Component.svelte';

// Test behavior, not implementation
const { getByText, rerender } = render(Component, { name: 'test' });
expect(getByText('test')).toBeInTheDocument();

// Re-render with new props instead of using component methods
await rerender({ name: 'updated' });
expect(getByText('updated')).toBeInTheDocument();

Quick Debugging Checklist

When you hit a broken pattern:

  1. Check the browser console first - lots of issues show as warnings before they become errors
  2. Look for @migration comments - grep for them, they tell you exactly what the tool couldn't handle
  3. Test in isolation - create a minimal reproduction in the Svelte Playground
  4. Check the migration tool's source - look at `svelte-migrate` to understand what patterns it recognizes

Remember: The migration tool is conservative - it prefers leaving you @migration comments to breaking your app. Those comments are your roadmap to manual fixes.

Most broken patterns follow the same theme: the migration tool handles simple, isolated patterns well but struggles with complex, interconnected logic. When debugging, try to break complex patterns into simpler pieces first.

Advanced Debugging Questions (When Basic Fixes Don't Work)

Q

I fixed all the @migration comments but my app still behaves differently. What now?

A

You're probably hitting subtle behavior changes between Svelte 4 and 5. The migration tool converts syntax but doesn't catch all behavior differences.

Common behavior changes to check:

  • Reactivity timing: Svelte 5's reactivity is more precise. Effects that ran multiple times in Svelte 4 might only run once now.
  • Component initialization order: If your components depend on specific initialization timing, this might have changed.

Debug approach:

## Check for console warnings about deprecated patterns
## Open browser dev tools and look for yellow warnings

## Add debug logging to your effects
$effect(() => {
  console.log('Effect running with:', someValue);
  // your effect logic
});
Q

My custom stores work but give weird errors in the console

A

You probably have a mix of old store patterns and new rune patterns that create conflicts.

Look for this warning:

Warning: You have both runes and reactive statements in the same component

Fix: Choose one approach consistently. Either:

  1. Keep stores as stores (recommended for shared state):

    // stores.js - keep this pattern
    import { writable } from 'svelte/store';
    export const myStore = writable(initialValue);
    
  2. Convert to runes completely (for component-local state):

    <!-- component.svelte -->
    <script>
      let localState = $state(initialValue);
      // Don't mix with stores
    </script>
    

Don't try to use both patterns in the same component - it confuses the reactivity system.

Q

Performance got worse after migration. Is this normal?

A

Sometimes, yes. The migration tool creates compatibility layers that can slow things down temporarily.

Check for these performance killers:

Unnecessary compatibility imports:

<!-- If you see lots of these, you have work to do -->
import { createEventDispatcher } from 'svelte';
import { tick } from 'svelte';

Over-reactive effects:

<!-- This runs on every state change -->
$effect(() => {
  // Don't put everything in one huge effect
  handleUserChanges();
  handlePermissionChanges();
  handleDataChanges();
});

Fix: Split into targeted effects:

<!-- Better: specific effects for specific changes -->
$effect(() => {
  handleUserChanges();
});

$effect(() => {
  handlePermissionChanges();
});
Q

I'm getting "hydration mismatch" errors that didn't exist before

A

SSR/hydration behavior changed slightly in Svelte 5. Usually this means client and server render different content.

Debug approach:

## Check if it's a specific component
grep -r "hydration" src/

## Look for conditional rendering that might differ between server/client
grep -r "browser\|document\|window" src/

Common causes:

  • Date/time rendering differences between server and client
  • User-specific content that renders differently
  • Browser-only APIs being called during SSR

Quick fix: Use {#if browser} blocks for browser-only content:

<script>
  import { browser } from '$app/environment';
</script>

{#if browser}
  <BrowserOnlyComponent />
{/if}
Q

Components work in development but break in production

A

This usually means your build process isn't handling Svelte 5 correctly.

Check your build config:

  1. Vite config might need updates for Svelte 5
  2. TypeScript config might be too strict for new patterns
  3. Your bundler might not understand rune syntax

Debug production issues:

## Build locally and test
npm run build
npm run preview

## Check build output for errors
npm run build 2>&1 | grep -E "(error|ERROR|warning|WARNING)"

Common production-only issues:

  • CSS gets stripped incorrectly
  • Dead code elimination removes needed imports
  • Minification breaks rune syntax
Q

My VSCode extension is showing errors but the app works fine

A

The language server sometimes lags behind Svelte releases or gets confused by mixed syntax.

Fixes to try:

  1. Restart the language server: Cmd/Ctrl+Shift+P → "Svelte: Restart Language Server"
  2. Update the extension: Make sure you have the latest Svelte extension
  3. Check your workspace settings: Sometimes project-specific settings break things

If errors persist:

## Check if it's a real TypeScript error
npx tsc --noEmit

## vs just a language server issue
Q

I want to revert specific components but keep others migrated

A

You can mix Svelte 4 and 5 syntax in the same app, but there are gotchas.

Safe to mix:

  • Components using old syntax in a Svelte 5 project
  • Stores remain as stores while some components use runes

Not safe to mix:

  • Runes and reactive statements in the same component
  • Old and new event handling patterns in parent/child relationships

Reverting specific components:

## Revert individual files
git checkout HEAD~1 -- src/components/problematic-component.svelte

## Or use VS Code to undo specific changes
Q

Tests pass but end-to-end tests fail

A

E2E tests might be hitting timing differences or behavior changes that unit tests miss.

Common E2E issues after migration:

  • Page load timing changed
  • Event handling timing is different
  • Animation/transition timing changed

Debug approach:

## Add more explicit waits in your E2E tests
await page.waitForSelector('[data-testid="component-loaded"]');

## Instead of assuming timing
await page.waitForTimeout(1000); // bad

Better E2E patterns for Svelte 5:

  • Wait for specific elements, not time
  • Test user interactions, not implementation details
  • Use data attributes for test targeting
Q

My migration worked but deployment failed

A

Deployment environments sometimes have different requirements than development.

Check these deployment-specific issues:

  1. Node version: Make sure production uses Node 16+
  2. Build environment: CI might need dependency updates
  3. Environment variables: Svelte 5 might handle env vars differently

Debug deployment:

## Test your production build locally
NODE_ENV=production npm run build
npm run preview

## Check if it's environment-specific
npm run build -- --mode production
Q

Everything works but bundle size got huge

A

The migration tool sometimes adds unnecessary compatibility imports and doesn't clean up dead code.

Find bloat:

## Analyze your bundle
npm run build -- --analyze

## Or use a bundle analyzer
npx vite-bundle-analyzer dist/

Common bloat sources:

  • Unused compatibility imports
  • Old stores that could be converted to runes
  • Duplicate dependencies (old + new versions)

Cleanup:

## Remove unused imports
npx depcheck

## Update all dependencies to latest compatible versions
npx npm-check-updates -u

Remember: Migration success isn't just "it compiles" - it's "it works the same way with better performance." Budget time for post-migration optimization, especially for production apps.

Debugging Resources (Where to Find Real Solutions)

Related Tools & Recommendations

integration
Recommended

Vite + React 19 + TypeScript + ESLint 9: Actually Fast Development (When It Works)

Skip the 30-second Webpack wait times - This setup boots in about a second

Vite
/integration/vite-react-typescript-eslint/integration-overview
100%
tool
Recommended

Vite Performance Optimization - When Your Build Speed Goes to Shit

for devs whose vite setup is now slower than a windows 95 bootup

Vite
/brainrot:tool/vite/performance-optimization
76%
compare
Recommended

Vite vs Webpack vs Turbopack vs esbuild vs Rollup - Which Build Tool Won't Make You Hate Life

I've wasted too much time configuring build tools so you don't have to

Vite
/compare/vite/webpack/turbopack/esbuild/rollup/performance-comparison
76%
integration
Recommended

SvelteKit + TypeScript + Tailwind: What I Learned Building 3 Production Apps

The stack that actually doesn't make you want to throw your laptop out the window

Svelte
/integration/svelte-sveltekit-tailwind-typescript/full-stack-architecture-guide
67%
review
Recommended

ESLint + Prettier Setup Review - The Hard Truth About JavaScript's Golden Couple

After 7 years of dominance, the cracks are showing

ESLint
/review/eslint-prettier-setup/performance-usability-review
57%
compare
Recommended

Selenium nervt wie sau, aber weißt du was noch mehr nervt?

Migration auf Playwright: sollte 2 Wochen dauern, waren dann 8 Monate. Typisch halt.

Playwright
/de:compare/playwright-vs-cypress-vs-selenium/enterprise-migration-reality
54%
tool
Recommended

Playwright - Fast and Reliable End-to-End Testing

Cross-browser testing with one API that actually works

Playwright
/tool/playwright/overview
54%
compare
Recommended

Playwright vs Cypress - Which One Won't Drive You Insane?

I've used both on production apps. Here's what actually matters when your tests are failing at 3am.

Playwright
/compare/playwright/cypress/testing-framework-comparison
54%
tool
Recommended

Storybook - Build Components Without Your App's Bullshit

The tool most frontend teams end up using for building components in isolation

Storybook
/tool/storybook/overview
51%
integration
Recommended

Deploying Deno Fresh + TypeScript + Supabase to Production

How to ship this stack without losing your sanity (or taking down prod)

Deno Fresh
/integration/deno-fresh-supabase-typescript/production-deployment
50%
howto
Recommended

TypeScript setup that actually works

Set up TypeScript without spending your entire weekend debugging compiler errors

TypeScript
/brainrot:howto/setup-typescript/complete-setup-guide
50%
tool
Similar content

sv migrate - Saves You From Manual Migration Hell

Learn how sv migrate simplifies Svelte upgrades, from understanding its capabilities to real-world usage and troubleshooting common issues. Avoid manual migrati

Svelte CLI
/tool/sv-migrate/overview
48%
integration
Recommended

![Docker Logo](https://www.docker.com/wp-content/uploads/2022/03/horizontal-logo-monochromatic-white.png) ![Kubernetes Logo](https://upload.wikimedia.org/wikipedia/commons/3/39/Kuberneteslogowithout_workmark.svg) VS Code Dev Containers + Docker + Kubernetes Integration

Skip the "Works on My Machine" Bullshit

VS Code Dev Containers
/integration/vscode-devcontainers-docker-kubernetes/overview
32%
tool
Recommended

VS Code 中国安装配置指南 - 解决网络问题的实用指南

专为中国开发者优化的安装和配置方案,解决常见的网络、下载和中文化问题

Visual Studio Code
/zh:tool/vscode/installation-setup-china-guide
32%
compare
Recommended

VS Code vs Cursor - どっちが本当に使えるのか?

3ヶ月使い倒した結論:AIエディタ戦争の現実

Visual Studio Code
/ja:compare/vscode/cursor/ai-feature-comparison
32%
tool
Recommended

ESLint - Find and Fix Problems in Your JavaScript Code

The pluggable linting utility for JavaScript and JSX

eslint
/tool/eslint/overview
32%
tool
Recommended

Fix Prettier Plugin Conflicts - The Debugging Guide That Actually Works

When your Prettier plugins hate each other more than your ex-coworkers

Prettier
/tool/prettier/plugin-troubleshooting
32%
tool
Recommended

Prettier - Opinionated Code Formatter

integrates with Prettier

Prettier
/tool/prettier/overview
32%
troubleshoot
Similar content

PostgreSQL Connection Pool Exhausted - Here's the Fix

Database looks fine but users getting timeout errors? Your app's connection pool is fucked.

PostgreSQL
/troubleshoot/postgresql-connection-pool-exhaustion/connection-pool-exhaustion-fixes
30%
tool
Recommended

Drizzle Kit - SQL Migration CLI That Actually Works

Tired of migrations breaking your deployments? Drizzle Kit is the CLI companion to Drizzle ORM that generates readable SQL migrations automatically, handles sch

Drizzle Kit
/tool/drizzle-kit/overview
29%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization