How to fix FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory in Node.js

Node.jsINTERMEDIATECRITICALUpdated Dec 9, 2025· 211 views

This fatal error occurs when a Node.js process attempts to allocate more memory than the available heap size allows. The process crashes because it cannot continue execution without the requested memory allocation.

Quick fix

Fixes ENOMEM

# Set heap size to 4GB (4096 MB)
node --max-old-space-size=4096 app.js

# For npm scripts, add to package.json
"scripts": {
  "start": "node --max-old-space-size=4096 server.js",
  "build": "node --max-old-space-size=4096 node_modules/.bin/webpack"
}
  1. Increase Node.js heap size using --max-old-space-size flag
  2. Set NODE_OPTIONS environment variable permanently
  3. Profile memory usage to identify leaks
  4. Optimize code for memory efficiency
node.js — error
# Set heap size to 4GB (4096 MB)
node --max-old-space-size=4096 app.js
# For npm scripts, add to package.json
"scripts": {
"start": "node --max-old-space-size=4096 server.js",
"build": "node --max-old-space-size=4096 node_modules/.bin/webpack"
}
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

What this error means

This error indicates that your Node.js application has exhausted its allocated heap memory and cannot allocate additional memory for JavaScript objects. Node.js has a default maximum heap size (typically 512MB on 32-bit systems and around 1.4GB on 64-bit systems) as a V8 engine limitation. When your application tries to allocate memory beyond this limit, V8's garbage collector attempts multiple times to free up space (the "CALL_AND_RETRY_LAST" phase), and when all attempts fail, the process terminates with this fatal error. The error is particularly common during memory-intensive operations like building large applications with webpack or similar tools, processing large datasets, or when memory leaks cause gradual memory accumulation over time.

Typical symptoms

  • Application crashes immediately with a fatal error message
  • Process terminates during build steps (webpack, vite, rollup)
  • Error occurs when processing large files or datasets
  • Application runs fine initially but crashes after extended operation
  • Memory usage steadily increases until crash (visible in monitoring tools)
  • Error appears during npm/yarn build or compilation steps

Common causes

  1. Default Node.js heap size is insufficient for your application's memory requirements
  2. Memory leaks from unreleased references, unclosed connections, or circular dependencies
  3. Processing large files or datasets entirely in memory without streaming
  4. Build tools (webpack, vite) requiring more memory than allocated for bundling
  5. Accumulation of cached data without proper cleanup mechanisms
  6. Large dependency trees causing excessive memory consumption during installation
  7. Recursive operations without tail-call optimization consuming stack space
  8. System memory pressure from other running processes limiting available RAM

How to fix "FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory"

1Increase Node.js heap size using --max-old-space-size flag

The quickest solution is to increase the maximum heap size Node.js can use. Start your application with the --max-old-space-size flag:

bash
# Set heap size to 4GB (4096 MB)
node --max-old-space-size=4096 app.js

# For npm scripts, add to package.json
"scripts": {
  "start": "node --max-old-space-size=4096 server.js",
  "build": "node --max-old-space-size=4096 node_modules/.bin/webpack"
}

For build tools, you may need to set the NODE_OPTIONS environment variable:

bash
# Linux/macOS
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build

# Windows (PowerShell)
$env:NODE_OPTIONS="--max-old-space-size=4096"
npm run build

# Windows (cmd)
set NODE_OPTIONS=--max-old-space-size=4096 && npm run build

Adjust the size based on your system's available RAM. Common values are 2048 (2GB), 4096 (4GB), or 8192 (8GB).

2Set NODE_OPTIONS environment variable permanently

For a persistent solution, set NODE_OPTIONS in your environment:

Linux/macOS (.bashrc, .zshrc, or .profile):

bash
export NODE_OPTIONS="--max-old-space-size=4096"

Windows (System Environment Variables):
1. Open System Properties → Advanced → Environment Variables
2. Add a new System Variable:
- Variable name: NODE_OPTIONS
- Variable value: --max-old-space-size=4096

Docker/Container environments:

dockerfile
ENV NODE_OPTIONS="--max-old-space-size=4096"

In .env files (with dotenv):

bash
NODE_OPTIONS=--max-old-space-size=4096

Restart your terminal or application after setting environment variables.

3Profile memory usage to identify leaks

Use Node.js profiling tools to identify memory-intensive code:

bash
# Run with inspector enabled
node --inspect app.js

# Or with explicit memory monitoring
node --inspect --trace-gc app.js

Then open Chrome DevTools:
1. Navigate to chrome://inspect
2. Click "inspect" under your Node.js process
3. Go to the Memory tab
4. Take heap snapshots before and after operations
5. Compare snapshots to identify growing objects

Using clinic.js for automatic analysis:

bash
npm install -g clinic
clinic doctor -- node app.js

Look for:
- Objects that grow over time without being released
- Event listeners that aren't removed
- Cached data without size limits
- Unclosed database connections or file handles

4Optimize code for memory efficiency

Refactor memory-intensive operations:

Use streaming instead of loading entire files:

javascript
// Bad: loads entire file into memory
const data = fs.readFileSync('large-file.json', 'utf8');
const json = JSON.parse(data);

// Good: streams data in chunks
const stream = fs.createReadStream('large-file.json');
const parser = JSONStream.parse('*');
stream.pipe(parser);
parser.on('data', (chunk) => {
  // Process each chunk
});

Implement pagination for large datasets:

javascript
// Bad: loads all records
const allRecords = await db.users.findMany();

// Good: processes in batches
const pageSize = 100;
let page = 0;
while (true) {
  const records = await db.users.findMany({
    skip: page * pageSize,
    take: pageSize
  });
  if (records.length === 0) break;
  // Process records
  page++;
}

Clear references and use WeakMap for caches:

javascript
// Use WeakMap for automatic garbage collection
const cache = new WeakMap();

// Explicitly null out large objects when done
largeObject = null;
5Fix memory leaks from event listeners and timers

Ensure proper cleanup of event listeners and intervals:

javascript
// Bad: event listener never removed
eventEmitter.on('data', handler);

// Good: remove when done
eventEmitter.on('data', handler);
// Later...
eventEmitter.removeListener('data', handler);

// Better: use once() for single-use listeners
eventEmitter.once('data', handler);

// Clear intervals and timeouts
const interval = setInterval(() => {}, 1000);
// Later...
clearInterval(interval);

// Use AbortController for cleanup
const controller = new AbortController();
eventEmitter.on('data', handler, { signal: controller.signal });
// Later...
controller.abort(); // Removes all listeners

Check for circular references:

javascript
// Bad: creates circular reference
const obj1 = {};
const obj2 = { ref: obj1 };
obj1.ref = obj2; // Circular reference

// Good: avoid or break circular references
obj1.ref = null; // Break the cycle when done
6Optimize build tool configuration

For build-time errors, optimize webpack/vite configuration:

webpack.config.js:

javascript
module.exports = {
  mode: 'production',
  optimization: {
    minimize: true,
    usedExports: true, // Tree shaking
    splitChunks: {
      chunks: 'all', // Split large bundles
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  },
  // Reduce memory usage during builds
  stats: 'errors-only',
  performance: {
    hints: false
  }
};

vite.config.js:

javascript
export default {
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor';
          }
        }
      }
    }
  }
};

Advanced notes

Understanding V8 memory structure: V8's heap is divided into spaces: New Space (for short-lived objects), Old Space (for long-lived objects), Large Object Space, and Code Space. The --max-old-space-size flag specifically controls the Old Space limit, which is typically where memory issues occur as objects are promoted from New Space.

OS-level memory limits: On Linux systems, check ulimit settings that may restrict memory: ulimit -v shows virtual memory limits. Container environments (Docker, Kubernetes) have their own memory limits that may be lower than Node.js heap settings.

32-bit vs 64-bit considerations: 32-bit Node.js processes cannot address more than ~1.5GB of memory regardless of --max-old-space-size settings. Always use 64-bit Node.js for memory-intensive applications.

Alternative memory management flags:
- --max-semi-space-size: Controls New Space size (rarely needed)
- --optimize-for-size: Reduces memory footprint at the cost of performance
- --expose-gc: Allows manual garbage collection via global.gc()

Monitoring production memory: Use tools like PM2, New Relic, or Datadog to monitor memory trends in production. Set up alerts for memory usage above 80% to catch issues before crashes occur.

Frequently asked questions

What does "ENOMEM" mean?
js application has exhausted its allocated heap memory and cannot allocate additional memory for JavaScript objects. 4GB on 64-bit systems) as a V8 engine limitation. When your application tries to allocate memory beyond this limit, V8's garbage collector attempts multiple times to free up space (the "CALL_AND_RETRY_LAST" phase), and when all attempts fail, the process terminates with this fatal error.
How do I fix "ENOMEM"?
This fatal error occurs when a Node.js process attempts to allocate more memory than the available heap size allows. The process crashes because it cannot continue execution without the requested memory allocation.
What causes "ENOMEM"?
Default Node.js heap size is insufficient for your application's memory requirements Memory leaks from unreleased references, unclosed connections, or circular dependencies Processing large files or datasets entirely in memory without streaming
Is the "ENOMEM" error serious?
Yes. This is a critical-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading