Tests that worked fine on Windows are failing with an IOException on Ubuntu.

I have a set of integration tests that have been working great on Windows for quite some time. While troubleshooting an unrelated issue I was running my tests on Ubuntu 20.04 LTS via WSL, and about half of the tests were failing with this IOException.

The Error Message

System.IO.IOException : The configured user limit (128) on the number of inotify instances has been reached, or the per-process limit on the number of open file descriptors has been reached.

It seems that due to the way my tests work using WebApplicationFactory<Startup> and calling factory.WithWebHostBuilder(builder => ..., I'm creating too many instances of the HostBuilder, which by default installs a file system watcher on the appsettings.json file. All those instances tap out the default number of inotify instances allowed. Switching to a polling mechanism clears this up.

The Solution I Found

Configure the environment variable to have dotnet use polling instead.


I don't know if there are unintended side effects of this change; however, since its only applying to test runs, I feel its a safe change to make.

HTTP Status Codes Explained for Most Folks

There are lots of jokes about HTTP status codes, what they mean, and general frustration with the inconsistent way in which they're used.

HTTP 1xx

  • 100: Continue sending me the request.

HTTP 2xx

  • 200: OK, here you go.
  • 201: OK, I created it for you.

HTTP 3xx

  • 301: Moved what you want to a new spot over here.
  • 302: Found what you're looking for over here.

HTTP 4xx

  • 400: Your bad.
  • 401: You aren't logged in.
  • 403: You're logged in, but can't do/see that.

HTTP 5xx: Our bad

  • 500: We screwed up.
  • 503: We forgot to start the server.

There are many more status codes, and as a developer I ecourage other developers to use appropriate and specific response codes. For more specific details, Wikipedia has a good overview.

Implied route parameters in ASP.NET Core Form Tag Halpers

With a route like /change/{id} the ID parameter is implicitly implied if the view contains a form with method="post" back to the same action name, for example:


<asp-form asp-action="change" method="post">


public ActionResult Change(int id, Model model)

When changing the form action to to include a change confirmation step:

<asp-form asp-action="confirmChange" method="post">

The id route parameter was not included by default anymore, so the controller action was receiving a default(int):

public ActionResult ConfirmChange(int id, Model model)

ASP.NET Core seems to include the current route parameters when posting back to the same action name.

The fix was fairly simple, you must explicitly include the route parameters on the <asp-form> tag when posting across action names.

<asp-form asp-action="change" asp-route-id="@Model.SomeId" method="post">

See also: Stack Overflow on updating route parameters.