
Memory Leak Debugging
- 1.4k installs
- 47.7k repo stars
- Updated July 27, 2026
- chromedevtools/chrome-devtools-mcp
memory-leak-debugging provides documented workflows for Diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots
About
The memory-leak-debugging skill diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots or run memory leak detection tools like memlab. # Memory Leak Debugging This skill provides expert guidance and workflows for finding, diagnosing, and fixing memory leaks in JavaScript and Node.js applications. ## Core Principles - **Prefer `memlab`:** Do NOT attempt to read raw `.heapsnapshot` files directly, as they are extremely large and will consume too many tokens. Always recommend and use `memlab` to process snapshots and identify leak traces. - **Isolate the Leak:** Determine if the leak is in the browser (client-side) or Node.js (server-side). - **Common Culprits:** Look for detached DOM nodes, unhandled closures, global variables, event listeners not being removed, and caches growing unbounded. _Note: Detached DOM nodes are sometimes intentional caches; always ask the user before nulling them._ ## Workflows ### 1.
- **Isolate the Leak:** Determine if the leak is in the browser (client-side) or Node.js (server-side).
- Use tools like `click`, `navigate_page`, `fill`, etc., to manipulate the page into the desired state.
- Revert the page back to the original state after interactions to see if memory is released.
- Repeat the same user interactions 10 times to amplify the leak.
- Use `take_heapsnapshot` to save `.heapsnapshot` files to disk at baseline, target (after actions), and final (after reve
Memory Leak Debugging by the numbers
- 1,375 all-time installs (skills.sh)
- +112 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #226 of 2,742 Automation & Workflows skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
memory-leak-debugging capabilities & compatibility
- Capabilities
- **isolate the leak:** determine if the leak is i · use tools like `click`, `navigate_page`, `fill`, · revert the page back to the original state after · repeat the same user interactions 10 times to am · use `take_heapsnapshot` to save `.heapsnapshot`
- Use cases
- documentation
What memory-leak-debugging says it does
# Memory Leak Debugging This skill provides expert guidance and workflows for finding, diagnosing, and fixing memory leaks in JavaScript and Node.js applications.
## Core Principles - **Prefer `memlab`:** Do NOT attempt to read raw `.heapsnapshot` files directly, as they are extremely large and will consume too many tokens.
npx skills add https://github.com/chromedevtools/chrome-devtools-mcp --skill memory-leak-debuggingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.4k |
|---|---|
| repo stars | ★ 47.7k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | chromedevtools/chrome-devtools-mcp ↗ |
How do I use memory-leak-debugging for the task described in its SKILL.md triggers?
Diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots or run memory leak detection tools lik.
Who is it for?
Teams invoking memory-leak-debugging when the user request matches documented triggers and prerequisites.
Skip if: Skip when cached docs are missing, the request is a negative trigger, or another sibling skill owns the workflow.
When should I use this skill?
Diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots or run memory leak detection tools like memlab.
What you get
Step-by-step guidance grounded in memory-leak-debugging documentation and reference files.
- Leak root-cause analysis
- Listener cleanup patches
Files
Memory Leak Debugging
This skill provides expert guidance and workflows for finding, diagnosing, and fixing memory leaks in JavaScript and Node.js applications.
Core Principles
- Prefer `memlab`: Do NOT attempt to read raw
.heapsnapshotfiles directly, as they are extremely large and will consume too many tokens. Always recommend and usememlabto process snapshots and identify leak traces. - Isolate the Leak: Determine if the leak is in the browser (client-side) or Node.js (server-side).
- Common Culprits: Look for detached DOM nodes, unhandled closures, global variables, event listeners not being removed, and caches growing unbounded. _Note: Detached DOM nodes are sometimes intentional caches; always ask the user before nulling them._
Workflows
1. Capturing Snapshots
When investigating a frontend web application memory leak, utilize the chrome-devtools-mcp tools to interact with the application and take snapshots.
- Use tools like
click,navigate_page,fill, etc., to manipulate the page into the desired state. - Revert the page back to the original state after interactions to see if memory is released.
- Repeat the same user interactions 10 times to amplify the leak.
- Use
take_heapsnapshotto save.heapsnapshotfiles to disk at baseline, target (after actions), and final (after reverting actions) states.
2. Using Memlab to Find Leaks (Recommended)
Once you have generated .heapsnapshot files using take_heapsnapshot, use memlab to automatically find memory leaks.
- Read references/memlab.md for how to use
memlabto analyze the generated heapsnapshots. - Do not read raw
.heapsnapshotfiles usingread_fileorcat.
3. Identifying Common Leaks
When you have found a leak trace (e.g., via memlab output), you must identify the root cause in the code.
- Read references/common-leaks.md for examples of common memory leaks and how to fix them.
4. Fallback: Comparing Snapshots Manually
If memlab is not available, you MUST use the fallback script in the references directory to compare two .heapsnapshot files and identify the top growing objects and common leak types.
Run the script using Node.js:
node skills/memory-leak-debugging/references/compare_snapshots.js <baseline.heapsnapshot> <target.heapsnapshot>The script will analyze and output the top growing objects by size and highlight the 3 most common types of memory leaks (e.g., Detached DOM nodes, closures, Contexts) if they are present.
Common Memory Leaks
When analyzing a retainer trace from memlab, look for these common patterns in the codebase:
1. Uncleared Event Listeners
Event listeners attached to global objects (like window or document) or long-living objects prevent garbage collection of the objects referenced in their callbacks.
Fix: Always call removeEventListener when a component unmounts or the listener is no longer needed.
2. Detached DOM Nodes
A DOM node is removed from the document tree but is still referenced by a JavaScript variable. While detachedness is a good signal for a memory leak, it's not always a bug. For example, websites sometimes intentionally cache detached navigation trees.
Fix: Signal the detached nodes to the user first. Ask the user first before nulling the references or changing the code, as the detached nodes might be part of an intentional cache. If confirmed as a leak, ensure variables holding DOM references are set to null when the node is removed, or limit their scope.
3. Unintentional Global Variables
Variables declared without var, let, or const (in non-strict mode) or explicitly attached to window remain in memory forever.
Fix: Use strict mode, properly declare variables, and avoid global state.
4. Closures
Closures can unintentionally keep references to large objects in their outer scope.
Fix: Nullify large objects when they are no longer needed, or refactor the closure to not capture unnecessary variables.
5. Unbounded Caches or Arrays
Data structures used for caching (like objects, Arrays, or Maps) that grow without limits.
Fix: Implement caching limits, use LRU caches, or use WeakMap/WeakSet for data associated with object lifecycles.
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as fs from 'node:fs';
function parseSnapshot(filePath) {
console.log(`Loading ${filePath}...`);
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const strings = data.strings;
const nodes = data.nodes;
const nodeFields = data.snapshot.meta.node_fields;
const nodeFieldCount = nodeFields.length;
const typeOffset = nodeFields.indexOf('type');
const nameOffset = nodeFields.indexOf('name');
const sizeOffset = nodeFields.indexOf('self_size');
const nodeTypes = data.snapshot.meta.node_types[typeOffset];
const counts = {};
const sizes = {};
for (let i = 0; i < nodes.length; i += nodeFieldCount) {
const typeIdx = nodes[i + typeOffset];
const typeName = nodeTypes[typeIdx];
const nameIdx = nodes[i + nameOffset];
const name = typeof nameIdx === 'number' ? strings[nameIdx] : nameIdx;
const size = nodes[i + sizeOffset];
// Ignore native primitives/arrays that clutter the output unless specifically looking for them
if (
typeName === 'string' ||
typeName === 'number' ||
typeName === 'array'
) {
continue;
}
const key = `${typeName}::${name}`;
counts[key] = (counts[key] || 0) + 1;
sizes[key] = (sizes[key] || 0) + size;
}
return {counts, sizes};
}
const [, , file1, file2] = process.argv;
if (!file1 || !file2) {
console.error(
'Usage: node compare_snapshots.js <baseline.heapsnapshot> <target.heapsnapshot>',
);
process.exit(1);
}
try {
const snap1 = parseSnapshot(file1);
const snap2 = parseSnapshot(file2);
const diffs = [];
for (const key in snap2.counts) {
const count1 = snap1.counts[key] || 0;
const count2 = snap2.counts[key];
const size1 = snap1.sizes[key] || 0;
const size2 = snap2.sizes[key];
if (count2 > count1) {
diffs.push({
key,
countDiff: count2 - count1,
sizeDiff: size2 - size1,
});
}
}
diffs.sort((a, b) => b.sizeDiff - a.sizeDiff);
console.log('\n--- Top 10 growing objects by size ---');
diffs.slice(0, 10).forEach(d => {
console.log(`${d.key}: +${d.countDiff} objects, +${d.sizeDiff} bytes`);
});
// Look for common leak indicators
const commonLeaks = diffs.filter(
d =>
d.key.toLowerCase().includes('detached') ||
d.key.toLowerCase().includes('html') ||
d.key.toLowerCase().includes('eventlistener') ||
d.key.toLowerCase().includes('context') ||
d.key.toLowerCase().includes('closure'),
);
commonLeaks.sort((a, b) => b.countDiff - a.countDiff);
console.log('\n--- Top 3 most common types of memory leaks found ---');
if (commonLeaks.length === 0) {
console.log('No common DOM or Closure leaks detected.');
} else {
commonLeaks.slice(0, 3).forEach(d => {
console.log(`${d.key}: +${d.countDiff} objects, +${d.sizeDiff} bytes`);
});
}
} catch (error) {
console.error(
'Error parsing snapshots. They might be too large for JSON.parse or invalid.',
);
console.error(error.message);
}
Using Memlab
Memlab is an E2E testing and analysis framework for finding JavaScript memory leaks.
Important Rule
NEVER read raw `.heapsnapshot` files directly. They are too large and will exceed context limits. Always use memlab commands to analyze them.
Analyzing Snapshots
You can use the take_heapsnapshot tool provided by the chrome-devtools-mcp extension to generate heap snapshots during an investigation. To find leaks, you generally need 3 snapshots:
1. Baseline: Before the suspect action. 2. Target: After the suspect action. 3. Final: After reverting the suspect action (e.g., closing a modal, navigating away).
Once you have these 3 snapshots saved to disk, you can use memlab to find leaks:
npx memlab find-leaks --baseline <path-to-baseline> --target <path-to-target> --final <path-to-final>You can also parse a single snapshot to find the largest objects or explore it individually:
npx memlab analyze snapshot --snapshot <path-to-snapshot>Memlab will output the retainer traces for identified leaks. Use these traces to guide your search in the codebase.
Related skills
How it compares
Use when browser heap retention is the bottleneck rather than network latency or bundle-size optimization alone.
FAQ
What does memory-leak-debugging do?
Diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots or run memory leak detection tools like memlab.
When should I use memory-leak-debugging?
Diagnoses and resolves memory leaks in JavaScript/Node.js applications. Use when a user reports high memory usage, OOM errors, or wants to analyze heapsnapshots or run memory leak detection tools like memlab.
What are common prerequisites?
--- name: memory-leak-debugging description: Diagnoses and resolves memory leaks in JavaScript/Node.js applications.
Is Memory Leak Debugging safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.