JavaScript memory leak in Svelte
A memory leak means the heap grows every time you navigate or interact and never comes back down, until long sessions jank, stutter, and eventually crash the tab. It is one of the hardest bugs to catch in review because it only shows up over time — the happy-path click looks fine. AI-generated effects and subscriptions are a frequent source: the setup is written, the cleanup is forgotten.
Symptoms
How VibeCheck catches it
In your widget · Problems
Potential memory leak (27% growth)
To your coding agent · MCP
agent › get_detected_issues
→ { detector: "memory-leak", issue: "Potential memory leak (27% growth)", threshold: "> 10% heap growth over 30s without GC recovery (warning), > 25% (error)" }
The same string in your widget and in your agent’s context — no screenshot, no copy-paste.
Root causes
The fix for Svelte
In Svelte 5, return a cleanup from $effect; in Svelte 4 use onDestroy. Either releases the resource when the component is torn down.
<script lang="ts">
$effect(() => {
const id = setInterval(tick, 1000)
const onResize = () => (w = window.innerWidth)
window.addEventListener('resize', onResize)
return () => {
clearInterval(id)
window.removeEventListener('resize', onResize)
}
})
</script>Steps
- Audit every effect/lifecycle hook that adds a listener, timer, or subscription
- Return or register a cleanup that removes exactly what was added
- Bound caches and growing arrays with an eviction policy (e.g. LRU or max size)
FAQ
- How do I confirm it is really a leak and not normal growth?
- Take heap snapshots in DevTools Memory before and after repeating an action (e.g. navigate away and back a few times). If retained size keeps climbing and never drops after GC, it’s a leak. VibeCheck watches for exactly this: sustained growth with no recovery.
- React Strict Mode runs my effect twice — is that a leak?
- No, that is intentional in development to surface missing cleanup. If your cleanup is correct and idempotent, the double-invoke is harmless and doesn’t happen in production.
- What are detached DOM nodes?
- Nodes removed from the document but still referenced by JavaScript (a closure, a cached array, an event handler). They can’t be garbage-collected. Drop the reference when you remove the node.