Back to blog
    Engineering

    EMFILE vs ENFILE vs Inotify for Too Many Open Files

    Written by:OperateOperate TeamUpdated 10 min read

    Three unrelated Linux limits print too many open files. How EMFILE, ENFILE and the inotify limits differ, and where to read each one in a minute.

    EMFILE vs ENFILE vs Inotify for Too Many Open Files

    Quick Answer

    Three unrelated Linux limits print the same sentence. EMFILE means one process hit its own descriptor limit, ENFILE means the whole system ran out of file handles, and the inotify limits are per user and are reported as EMFILE or ENOSPC. Read the errno first, then check the matching limit, because raising the wrong one changes nothing and delays the real fix.

    EMFILE vs ENFILE is the first fork in any too many open files incident, and the inotify limits add a third branch that looks like a descriptor problem and is not. We think the fastest way through is to stop reading the message and read the errno instead.

    The message is a generic string. The number behind it names the ceiling you hit, and each ceiling lives in a different place and has a different fix.

    This post compares the three ceilings, shows how to read each limit on a live system, explains why inotify surprises people and says when raising a limit is the wrong move. For the leak-versus-load question and the full fix, we keep that in our field guide to file descriptor exhaustion.

    One Sentence Comes From Three Different Ceilings

    The three ceilings differ in scope. One belongs to a process, one belongs to the machine and one belongs to a user. A single table keeps them apart, and we would pin it next to the runbook.

    CeilingErrnoScopeWhere to read it
    Per-process descriptor limitEMFILE, 24One processThe Max open files line in the process limits file
    System-wide file tableENFILE, 23The whole kernelThe file-nr and file-max sysctls
    Inotify instancesEMFILE, 24One userThe max_user_instances sysctl
    Inotify watchesENOSPC, 28One userThe max_user_watches sysctl

    The fourth row is the one that misleads. It prints a message about disk space, so it looks like a full filesystem when no disk is involved, and responders lose time checking df.

    EMFILE vs ENFILE vs Inotify Is Settled by the Errno

    We start every one of these incidents the same way. If the application logs do not show the errno, trace the failing process for a few seconds. The calls that matter are open, socket, accept and the inotify calls, and the return value names the ceiling directly.

    strace -f -p PID -e trace=openat,socket,accept4,inotify_init1,inotify_add_watch

    1. EMFILE From a Process Limit

    The Linux manual page for open(2) describes EMFILE as "The per-process limit on the number of open file descriptors has been reached." The limit that counts is the effective limit of the running process, not what your terminal prints.

    grep "Max open files" /proc/PID/limits
    ls /proc/PID/fd | wc -l

    If the soft limit is 1024 and the process holds 1024 descriptors, you have hit EMFILE. A service started by systemd inherits its limit from the unit file, so a command run in your own shell tells you nothing about it.

    2. ENFILE From the System Table

    The same page describes ENFILE as "The system-wide limit on the total number of open files has been reached." This is the rare branch on modern hosts and the more likely one on a crowded shared node.

    cat /proc/sys/fs/file-nr

    The kernel's sysctl documentation says the three values in file-nr denote the number of allocated file handles, the number of allocated but unused file handles, and the maximum number of file handles. When the first value reaches the third, the table is full for every process on the machine.

    3. Inotify Instances and Watches

    Inotify has two user-wide ceilings. Creating an instance can fail with EMFILE because, in the words of the inotify_init(2) manual, "The user limit on the total number of inotify instances has been reached." Adding a watch can fail with ENOSPC because, per inotify_add_watch(2), "The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource."

    sysctl fs.inotify.max_user_instances fs.inotify.max_user_watches
    lsof -nP | grep inotify | awk '{print $1, $2}' | sort | uniq -c | sort -nr | head

    The second command lists the processes holding the most inotify handles, which usually names the offender in one screen. Run it as a privileged user, because other users' handles are hidden from an ordinary account, and we would expect an empty result from a normal shell to mean nothing.

    The table below condenses the three checks into one view, so a responder can run them in order without rereading the section.

    CheckCommand targetA full ceiling looks like
    Process limitThe limits file and fd directory of the processDescriptor count equal to the soft limit
    System tableThe file-nr sysctlAllocated handles equal to the maximum
    InotifyThe inotify sysctls and a per-process handle countOne user holding instances up to the limit

    Why Inotify Looks Like a Descriptor Problem and Is Not

    We think the inotify case is the one that costs the most time, because the usual evidence says everything is fine. The process holds a few dozen descriptors, the system table is nearly empty and the soft limit is generous. Yet the process cannot start a file watcher.

    The reason is scope. The inotify limits apply per user, so one noisy container or tool that leaks instances can block every other process running under the same user ID. The victim and the culprit are different processes, and process-level evidence points at the wrong one.

    Anything that watches files can hit this, including development servers, log shippers and configuration reloaders. When a tool reports that it could not create a watcher, we treat it as an inotify question first and a descriptor question second.

    Raising the Wrong Limit Changes Nothing

    Most advice stops at raising a limit, and the right limit depends on the errno. The table below pairs each symptom with the fix that works and the common fix that does not.

    ErrnoFix that worksFix that does nothing
    EMFILE from a processRaise the limit in the service definition, such as LimitNOFILE in a systemd unitRunning ulimit in an interactive shell
    ENFILEFind which process holds the most handles, then raise file-max if load is legitimateRaising the per-process limit further
    Inotify instancesRaise max_user_instances or stop the leaking watcherRaising the per-process limit
    Inotify watchesRaise max_user_watches or watch fewer pathsFreeing disk space

    For containers, the same idea applies at a different layer. Docker accepts a nofile value through its ulimit option when a container is started, and a web server such as nginx has its own worker setting for the same purpose. In both cases the number must reach the process that is failing.

    Go programs deserve a note. The Go 1.19 release notes say Go programs that import the os package now automatically raise the open file limit to the hard limit on Unix systems. A Go service that still hits EMFILE is therefore working against its hard limit, and that is where we would look.

    When Raising the Limit Is Not the Answer

    A raised limit is the right answer only when the count follows legitimate load and falls back when traffic does. If the number climbs and never recedes, the process is leaking descriptors, and a bigger ceiling only postpones the next crash by a few hours.

    We would not try to settle that question from the errno alone. The errno names the ceiling, while the shape of the descriptor count over time names the cause. Our guide to the leak test and the composition of the descriptor table covers it, and we link it above for that reason.

    Evidence for these incidents is scattered across process files, service units and container configuration. If you want an agent to gather it, we would start with one log source and one repository and judge it on an incident you already understand, with a person keeping the decision on the fix.

    A Sixty Second Triage Order

    This is the order we would follow when the page says too many open files and nobody knows which ceiling it is.

    1. Capture the errno from the logs, or from a short trace of the failing process.
    2. If it is 24, read the effective limit and the live descriptor count of that process.
    3. If it is 23, read the system file table and find the process holding the most handles.
    4. If the process looks healthy but cannot start a watcher, read the inotify limits and list handles by process.
    5. Decide between raising the limit and fixing a leak only after you know which ceiling you are on.

    Our notes on the other ENOSPC cases, where the disk is not full cover the sibling confusion for the inotify watch limit. Error strings with several unrelated causes are common, and our guide to attributing a connection reset to the component that sent it uses the same read-the-detail-first habit.

    Name the Ceiling Before You Raise Anything

    EMFILE vs ENFILE is a question about scope, and the inotify limits add a user-wide scope that no process-level check will reveal. Read the errno, read the matching limit and change only that one.

    We would put the table in the runbook this week, so the next responder spends the first minute on the right ceiling. When you want agents to read the effective limits and descriptor growth while your engineers decide, Operate runs dedicated AI agents that investigate production problems with cited evidence and propose fixes for your team to review.

    Frequently Asked Questions

    We read it as the kernel refusing to give a process another file, socket or pipe because some ceiling was reached. Which ceiling is the real question, since the per-process limit, the system-wide table and the inotify limits all print the same sentence.

    We usually find the change was made in a shell, while the failing service runs under systemd or a container runtime with its own limit. The setting also does not reach processes that are already running, so the effective limit of the live process is the number to check.

    Error 24 is EMFILE, the per-process descriptor limit. Error 23 is ENFILE, the system-wide limit on open files. We treat 24 as the common case and 23 as rare, though the inotify instance limit also surfaces as 24, which can mislead.

    We read the Max open files line in the limits file under the process ID in the proc filesystem, then compare it with the count of entries in that process's fd directory. The two numbers together show the limit and how close the process sits to it.

    We take it to mean a tool tried to create an inotify instance and the kernel refused, usually because the per-user instance limit was reached. It can appear while the process holds few descriptors, so we check the inotify limits and the other holders under the same user.

    About the author

    Operate

    Operate Team

    The team behind Operate

    Operate Team builds Operate, enterprise AI agents for production operations. Operate answers production questions from Slack and Microsoft Teams, investigates alerts, and reviews performance, security and cost. It finds the root cause with evidence and proposes a fix for an engineer to review, with controlled access to your systems.

    Share: X LinkedIn
    #linux
    #SRE
    #troubleshooting
    #devops

    Keep reading