How to Fix System.IO.IOException: The configured user limit on the number of inotify instances has been reached
Date: 2024-09-20 | create | tech | dotnet | asp-dotnet | fsharp | csharp | linux | unix |
I recently ran into a problem with one of my dotnet projects - TravelMap. It started throwing an exception System.IO.IOException: The configured user limit (8192) on the number of inotify instances has been reached
which crashed my app and blocked it from spinning up its webserver.
Here I'll share how I resolved it so hopefully it can unblock you as well.
App Setup and Overview
First a bit of context on the app itself and how it's hosted so you can understand the environment it was running in and get a better idea if this exception / fix is relevant to your app setup or not.
- App - ASP.NET webapp written in F#. Uses standard
Host.CreateDefaultBuilder()
- Hosting - Docker container running on Railway Linux Server (Hosting provider doesn't matter but container and Linux/Unix does)
For more information on TravelMap and how it's built, checkout the TravelMap project page
System.IO.IOException: inotify instances reached
The System IOException was thrown when my container tried to startup. On debugging it appeared that the container failed in configuration during startup.
The full exception message:
Unhandled exception. System.IO.IOException: The configured user limit (8192) on the number of inotify instances has been reached, or the per-process limit on the number of open file descriptors has been reached.
According to Stack Overflow this can often happen when running dotnet on Linux / Unix and is often caused by too many file watchers on a configuration file. This matched up with what I was doing and my exception's logs so is likely what caused this issue.
Fixing the Exception
One of the recommended ways to fix this exception is to set reloadOnChange=false
in the ConfigurationBuilder
for your file. This will prevent the builder from opening up additional file watchers and thus will not run into this issue.
I did this and it fixed my problem so seems to work.
My ConfigurationBuilder after the fix:
let fetchConfiguration (environment_name : string) =
let targetConfigurationFile = (
if environment_name.ToLower() = "development"
then "appsettings.Development.json"
else "appsettings.json")
let configurationRoot = (
(ConfigurationBuilder())
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(targetConfigurationFile, false, reloadOnChange=false)
.Build())
let root = configurationRoot.Get<AppConfiguration>()
root
Note: This fix works by preventing new filewatchers on configuration files - this means dotnet will not reload if this file changes. This is fine for my case because I know my configuration will never change during the lifecycle of my app - if there is a change, I would deploy a new container. For some cases this may not work (like local hotreloading) so use with discretion.
Next
This unblocked me and was pretty simple so I decided to log this for posterity in the hope that it helps others and saves me time when I inevitably run into this again. I've gone ahead and added this fix into CloudSeed (my F# project boilerplate for webapps) so that I can avoid this when spinning up new apps.
Want to get started building webapps with F#? Spin up a fullstack F# web app in 10 minutes with CloudSeed
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.