How to fix Error: EAGAIN: resource temporarily unavailable in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 155 views

The EAGAIN error indicates that a requested I/O operation cannot be completed immediately because the resource is temporarily unavailable. This is a recoverable error that signals Node.js to retry the operation later rather than failing permanently.

Quick fix

Fixes EAGAIN

# Check maximum open file descriptors
ulimit -n

# Check maximum user processes
ulimit -u

# View all limits
ulimit -a
  1. Check current system resource limits
  2. Implement retry logic for EAGAIN errors
  3. Increase system resource limits
  4. Fix file descriptor and process leaks
node.js โ€” error
# Check maximum open file descriptors
ulimit -n
# Check maximum user processes
ulimit -u
# View all limits
ulimit -a
Error: EAGAIN: resource temporarily unavailable

What this error means

The EAGAIN (Error AGAIn) error is a POSIX system-level error code that occurs when attempting to perform I/O operations on resources that are temporarily unavailable. In Node.js, this error commonly appears during file operations, reading from stdin, spawning child processes, or working with non-blocking I/O operations. Unlike permanent errors, EAGAIN indicates a transient condition - the operation failed not because of incorrect parameters or permissions, but because the system temporarily lacks the resources to complete it. This typically occurs when working with non-blocking file descriptors where data isn't immediately available for reading, or when system resource limits (like open file descriptors or process counts) are temporarily exhausted. The error is particularly common in high-throughput applications that perform many concurrent I/O operations, spawn numerous child processes, or work with streams and file descriptors extensively. Understanding that EAGAIN is temporary and recoverable is crucial for implementing proper error handling strategies.

Typical symptoms

  • Operations on fs.readFileSync(0) or process.stdin fail intermittently
  • child_process.spawn() or fork() operations fail with EAGAIN
  • File read/write operations throw EAGAIN during high load
  • Applications enter high CPU usage loops when spawning many processes
  • Error appears randomly during large test suites execution
  • Serial port or stdin reading operations fail unexpectedly

Common causes

  1. System has reached the maximum number of open file descriptors (ulimit -n)
  2. Process count limit has been exceeded (ulimit -u)
  3. Reading from stdin or file descriptor when no data is currently available
  4. Spawning too many child processes simultaneously without proper cleanup
  5. Non-blocking file descriptor operations attempted before data is ready
  6. System resource exhaustion from rogue processes or cron jobs
  7. File descriptor leaks from improperly closed streams or handles

How to fix "Error: EAGAIN: resource temporarily unavailable"

1Check current system resource limits

Verify your current ulimit settings to identify if you're hitting system constraints:

bash
# Check maximum open file descriptors
ulimit -n

# Check maximum user processes
ulimit -u

# View all limits
ulimit -a

On Linux, you can also check current file descriptor usage:

bash
# Count open file descriptors for current process
ls /proc/$$/fd | wc -l

# For a specific Node.js process
ls /proc/<PID>/fd | wc -l
2Implement retry logic for EAGAIN errors

Handle EAGAIN errors gracefully by retrying the operation after a short delay:

javascript
const fs = require('fs');

function readWithRetry(fd, buffer, offset, length, position, maxRetries = 3) {
  let retries = 0;

  while (retries < maxRetries) {
    try {
      return fs.readSync(fd, buffer, offset, length, position);
    } catch (error) {
      if (error.code === 'EAGAIN' && retries < maxRetries - 1) {
        retries++;
        // Brief delay before retry
        const start = Date.now();
        while (Date.now() - start < 10) {} // 10ms blocking wait
        continue;
      }
      throw error;
    }
  }
}

For async operations, use a more elegant retry approach:

javascript
async function readWithRetryAsync(fd, buffer, offset, length, position, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fs.promises.read(fd, buffer, offset, length, position);
    } catch (error) {
      if (error.code === 'EAGAIN' && i < maxRetries - 1) {
        await new Promise(resolve => setTimeout(resolve, 10));
        continue;
      }
      throw error;
    }
  }
}
3Increase system resource limits

Temporarily increase limits for your current session:

bash
# Increase file descriptor limit
ulimit -n 4096

# Increase process limit
ulimit -u 2048

For permanent changes on Linux, edit /etc/security/limits.conf:

bash
* soft nofile 4096
* hard nofile 8192
* soft nproc 2048
* hard nproc 4096

For systemd services, add to your service file:

ini
[Service]
LimitNOFILE=4096
LimitNPROC=2048

On macOS, edit /Library/LaunchDaemons/limit.maxfiles.plist or use launchctl.

4Fix file descriptor and process leaks

Ensure all file descriptors and child processes are properly closed:

javascript
const fs = require('fs');
const { spawn } = require('child_process');

// Always close file descriptors
const fd = fs.openSync('file.txt', 'r');
try {
  // perform operations
} finally {
  fs.closeSync(fd);
}

// Use graceful-fs for automatic retry handling
const gracefulFs = require('graceful-fs');
gracefulFs.readFile('file.txt', 'utf8', (err, data) => {
  // graceful-fs automatically retries on EAGAIN
});

// Properly manage child processes
const child = spawn('command', ['arg1', 'arg2']);

child.on('exit', (code) => {
  console.log(`Process exited with code ${code}`);
});

child.on('error', (error) => {
  if (error.code === 'EAGAIN') {
    console.error('Resource temporarily unavailable, retry later');
  }
});

// Limit concurrent child processes
const MAX_CONCURRENT = 10;
let activeProcesses = 0;
const queue = [];

function spawnWithLimit(command, args) {
  if (activeProcesses < MAX_CONCURRENT) {
    activeProcesses++;
    const child = spawn(command, args);
    child.on('exit', () => {
      activeProcesses--;
      if (queue.length > 0) {
        const next = queue.shift();
        spawnWithLimit(next.command, next.args);
      }
    });
    return child;
  } else {
    queue.push({ command, args });
  }
}
5Use graceful-fs for file operations

Install and use graceful-fs, which automatically handles EAGAIN and EMFILE errors:

bash
npm install graceful-fs

Replace native fs with graceful-fs:

javascript
// Instead of:
// const fs = require('fs');

// Use:
const fs = require('graceful-fs');

// All fs operations now automatically retry on EAGAIN
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('Error after retries:', err);
    return;
  }
  console.log(data);
});

Or patch fs globally at application startup:

javascript
const gracefulFs = require('graceful-fs');
gracefulFs.gracefulify(require('fs'));

Advanced notes

Understanding Non-Blocking I/O: EAGAIN is primarily associated with non-blocking file descriptors. When you read from a non-blocking fd and no data is available, the system returns EAGAIN instead of blocking the thread. Node.js internally handles this for streams and async operations, but sync operations or direct file descriptor access can expose this error.

Process Spawning Limits: When spawning child processes, EAGAIN can occur if the system hits the per-user process limit. On Linux, this is typically controlled by RLIMIT_NPROC. Applications that spawn many short-lived processes (like build tools or test runners) should implement process pooling to avoid this limit.

Stdin Reading Edge Cases: Reading from stdin using fs.readSync(0) can produce EAGAIN if stdin is non-blocking and no input is available. This is especially common when using stdin in TTY mode or after other libraries have modified stdin's flags. Consider using readline or process.stdin.read() which handle this automatically.

Container Environments: In Docker containers or Kubernetes pods, default ulimits may be lower than the host system. Always configure appropriate limits in your container specifications:

yaml
# Kubernetes example
spec:
  containers:
  - name: app
    resources:
      limits:
        cpu: "1"
        memory: "512Mi"
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        add: ["SYS_RESOURCE"]

File Descriptor Monitoring: For production applications, monitor file descriptor usage using process metrics. Many APM tools can track this, or use custom monitoring:

javascript
setInterval(() => {
  const used = process._getActiveHandles().length + process._getActiveRequests().length;
  console.log(`Active handles: ${used}`);
}, 60000);

Kernel Parameters: On Linux, system-wide limits are set in /proc/sys/fs/file-max (total file descriptors) and /proc/sys/kernel/pid_max (total processes). These kernel parameters may need adjustment on high-load servers.

Frequently asked questions

What does "EAGAIN" mean?
The EAGAIN (Error AGAIn) error is a POSIX system-level error code that occurs when attempting to perform I/O operations on resources that are temporarily unavailable. js, this error commonly appears during file operations, reading from stdin, spawning child processes, or working with non-blocking I/O operations. Unlike permanent errors, EAGAIN indicates a transient condition - the operation failed not because of incorrect parameters or permissions, but because the system temporarily lacks the resources to complete it.
How do I fix "EAGAIN"?
The EAGAIN error indicates that a requested I/O operation cannot be completed immediately because the resource is temporarily unavailable. This is a recoverable error that signals Node.js to retry the operation later rather than failing permanently.
What causes "EAGAIN"?
System has reached the maximum number of open file descriptors (ulimit -n) Process count limit has been exceeded (ulimit -u) Reading from stdin or file descriptor when no data is currently available
Is the "EAGAIN" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading