Fixing 'too many open files' In MacOS

Nanobox is a useful tool for building and deploying web applications. It supports all three of the most common operating systems used by web developers, more or less equally. Unfortunately, in those cases where things aren't quite the same, the rough edges are a bit beyond Nanobox's control, and you have to make changes to the system itself to smooth them out. One common example is the file system watcher.

Because Nanobox builds a development environment inside an isolated Docker container, your dev env won't be able to see changes you make to files outside the container, even though those files are mounted into the container for your app's runtime components to use. So Nanobox has to relay change events into the container for you. This is easily enabled in your boxfile.yml by adding fs_watch: true to your run.config section.

Where this becomes an issue is when your apps have a large number of files to watch for changes. Normally, Nanobox hooks into a feature called inotify, which asks the system kernel to alert it to changes as they happen. In order for this to work, though, Nanobox has to open a reference to the metadata of each file, and it can quickly run beyond the system's per-process limit on the number of open file references, normally controlled (on Linux and OS X) by a value called the ulimit. This is also the name of the tool used to change that value, and when Nanobox encounters the situation where it has run beyond that limit, it recommends using ulimit to change that value to something higher:

---------------------------------------------------------------------

An error occured in the fast notify watcher: 'too many open files'

Generally, having too low of a ulimit causes these issues.
Consider upping your ulimit to resolve (`ulimit -n 2048`).
Until then, we'll go ahead and rollover to a slower polling solution.

---------------------------------------------------------------------

For macOS Sierra and higher (10.12+), though, ulimit is no longer honored. Instead, you need to do the following:

  1. In /Library/LaunchDaemons create a file named limit.maxfiles.plist and paste the following in (feel free to change the two numbers, which are the soft and hard limits, respectively):
<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"  
        "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">  
  <dict>
    <key>Label</key>
    <string>limit.maxfiles</string>
    <key>ProgramArguments</key>
    <array>
      <string>launchctl</string>
      <string>limit</string>
      <string>maxfiles</string>
      <string>64000</string>
      <string>524288</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>ServiceIPC</key>
    <false/>
  </dict>
</plist>
  1. Change the owner of your new file:
sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist
  1. Load these new settings:
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist
  1. Finally, check that the limits are correct:
launchctl limit maxfiles

You may need to reboot to get this to actually apply, if the load step doesn't apply the changes properly.

This is only one of the rough spots you might encounter, but hopefully this article will be enough to help you smooth it out with ease. And as always, if you have any feedback to offer, it's always welcome in the comments below!

The above steps were researched and compiled by Gerard de Brieder. Thanks to him for helping us out!

Posted in MacOS, High Sierra, Live Reload

Daniel Hunsaker

Daniel Hunsaker

Author, Father, Programmer, Nut. Dan contributes to so many projects he sometimes gets them mixed up. He'll happily help you out on the Nanobox Slack server when the staff are offline.

@sendoshin Idaho, USA
Read More