Too Many Open Files / EMFILE (tested)
Too many open files (Python's OSError: [Errno 24], Node's EMFILE) means a process has more file descriptors open at once than its limit allows. We lowered the limit on a real Linux box, made it fail, captured the exact error text, then raised the limit and watched the same code succeed.
1. The limits on our test box
On our Debian 13 box, the per-process open-file limits were:
$ ulimit -Sn
524288
$ ulimit -Hn
524288
$ cat /proc/sys/fs/file-max
9223372036854775807
Those numbers are high because this is a modern distro default, not a tuned server. ulimit -Sn is the soft limit (what actually stops a process today). ulimit -Hn is the hard ceiling a non-root process can raise its own soft limit up to. /proc/sys/fs/file-max is a different, system-wide number (section 4) — on this box the kernel reports the architecture's maximum representable value, effectively uncapped.
2. Reproducing EMFILE on purpose
To actually see the error, we lowered the limit for one throwaway subshell only (never the real session) and ran a script that opens files in a loop:
$ bash -c 'ulimit -n 50; ulimit -n; python3 /tmp/openfiles_test.py'
50
OPENED=47
OSError: [Errno 24] Too many open files: '/tmp/ofd_test_47.txt'
With the soft limit set to 50, Python opened 47 files before the 48th call to open() raised. That "47, not 50" gap is real and expected: the process already had 3 descriptors in use for stdin, stdout and stderr, so only 47 slots were free for new files.
Node's own built-in fs module hits the same wall with its own wording:
$ bash -c 'ulimit -n 50; node /tmp/openfiles_test.js'
OPENED=30
EMFILE: too many open files, open '/tmp/ofd_node_30.txt'
Node stopped sooner, at 30 instead of 47, under the identical 50-descriptor limit. Node's runtime (libuv) keeps its own internal descriptors open for things like the event loop and its thread pool, so fewer slots are left for application code before the same EMFILE condition hits.
3. The fix: raise the limit (and confirm it actually works)
Raising the limit in the same kind of subshell let the identical script run much further before hitting the (now higher) wall:
$ bash -c 'ulimit -n 4096; ulimit -n; python3 /tmp/openfiles_test.py'
4096
OPENED=4093
OSError: [Errno 24] Too many open files: '/tmp/ofd_test_4093.txt'
Same script, same error type, but it now opened 4,093 files (again, 3 short of 4096) before failing — nearly 90× more than with the 50 limit. That confirms the ceiling moved because of ulimit -n, not because of anything else in the code. Our main shell's own limit was untouched the whole time:
$ ulimit -Sn
524288
In real code, the fix is almost never "raise the limit and keep looping" — it's closing file descriptors (and sockets, which share the same fd table on Linux) as soon as you're done with them, using with open(...) in Python or fs.close()/streams in Node, and pooling connections instead of opening a new one per request. Raising the limit (below) buys headroom for a process that legitimately needs many concurrent descriptors, like a server handling thousands of sockets.
4. Per-process limit vs. system-wide fs.file-max
These are two different ceilings, and our test only exercised the first one:
- Per-process limit (
ulimit -n,RLIMIT_NOFILE). What section 2 measured. It caps how many descriptors one process can hold open, regardless of how much headroom the rest of the system has. Every one of our EMFILE/Errno 24 errors came from this limit, not from the system running out of anything globally. - System-wide ceiling (
/proc/sys/fs/file-max). A kernel-wide cap on the total number of open file handles across every process on the machine combined. On this box it read9223372036854775807— effectively unbounded for any real workload. We only read this value; we did not change it, since it's a shared, persistent system setting.
In practice, EMFILE in a single script or server process (what this guide reproduces) is almost always the per-process limit. The system-wide limit matters on a busy multi-process host (many services, containers or user sessions) where individual processes stay under their own ulimit -n but the sum across all of them approaches fs.file-max. You'd see that as open() failures scattered across unrelated processes, not one process failing in isolation like ours did.
5. Making the fix persistent (per the Linux docs, not measured)
ulimit -n 4096 as used above only lasts for that one shell/process. Per the Linux and systemd documentation, to make a higher limit stick:
- Login shells / interactive users: add lines to
/etc/security/limits.conf(requires thepam_limitsmodule), for examplemyuser soft nofile 4096andmyuser hard nofile 65536. - systemd services: set
LimitNOFILE=4096(or higher) in the service's[Service]section, either in the unit file or an override viasystemctl edit. This applies regardless of who the service runs as and doesn't needpam_limits. - Docker containers: the
--ulimit nofile=4096:65536flag ondocker run, or the equivalentulimits:key in Compose.
We did not edit any of these files on our test box — they're persistent, system-level changes, so treat the above as what the docs describe, not something we verified here. Whatever mechanism you use, confirm it worked the same way we did in section 3: run the real workload and watch the actual descriptor count it reaches before any error, don't just trust the configured number.
Frequently asked questions
What does Errno 24 mean in Python?
Errno 24 is EMFILE on Linux: the calling process has too many file descriptors open already. We reproduced it directly: with ulimit -n 50, Python's open() raised OSError: [Errno 24] Too many open files after 47 successful opens.
Why did my script fail a few files before the exact ulimit number?
A few descriptors are already in use for stdin, stdout and stderr (and, in Node, for internal runtime/event-loop handles) before your code opens anything. In our test, a limit of 50 let Python open 47 new files and Node only 30, under the identical limit.
Is EMFILE the same as running out of disk space or memory?
No. EMFILE/Errno 24 is specifically about the count of open file descriptors hitting a limit, not disk space (ENOSPC) or memory. In our tests the disk had plenty of free space; the failure was purely the descriptor count.
Does raising fs.file-max fix EMFILE in my app?
Usually not. fs.file-max is a system-wide ceiling across every process; our EMFILE errors came entirely from the much smaller per-process ulimit -n, which is what you normally need to raise. We only read fs.file-max on our box; we didn't need to touch it to fix the test failure.
How do I raise the open-file limit for good, not just one shell?
ulimit -n in a shell only lasts for that shell and its children, as our tests showed (the main shell's limit of 524288 was unaffected by the subshell tests). Per the Linux docs, persistent changes go in /etc/security/limits.conf for login sessions or LimitNOFILE= in a systemd unit for services; we did not edit those files ourselves.
Written with AI assistance. Measured on 2026-10-02 on Debian GNU/Linux 13 (trixie) with Python 3.13.5 and Node.js 24.21.0. The persistent-fix section (limits.conf, systemd LimitNOFILE=) is per the Linux docs, not measured. PlainHeaders is our extension; Python and Node.js are free.