ubuntu-latest (Ubuntu 26.04) skips /etc/sysctl.conf: inotify "too many open files" and ThreadSanitizer "unexpected memory mapping"
ubuntu-latest is moving from Ubuntu 24.04 to 26.04 between October 19 and November 19, 2026 (what else changes). The image build writes a few kernel settings to /etc/sysctl.conf, but on 26.04 nothing reads that file at boot: Ubuntu dropped the /etc/sysctl.d/99-sysctl.conf link that made systemd load it (Launchpad #2084376, Won't Fix). The runner keeps the kernel's defaults, which the maintainers confirmed on x64 and Arm64 (runner-images #15108):
fs.inotify.max_user_instances: 128, not 1280fs.inotify.max_user_watches: 64097, not 655360vm.mmap_rnd_bits: 32 on x64, Ubuntu's kernel default, not 28
vm.max_map_count is in the same file but is not affected, because Ubuntu 26.04 already defaults it to 1048576.
The step that puts the values back
From the maintainers' reply on #15108. Put it at the start of the job, before anything that starts watchers or a cluster. On 24.04 it sets the values the image already has, so it is safe on both:
- name: Restore kernel parameters run: sudo sysctl -w fs.inotify.max_user_instances=1280 fs.inotify.max_user_watches=655360 vm.mmap_rnd_bits=28
The image change that would make the step unnecessary is proposed in runner-images #15146 and was not merged on November 4. ubuntu-slim runs as a container and gets these limits from the host kernel, so its own sysctl settings are not applied either way.
.NET: "The configured user limit (128) on the number of inotify instances has been reached"
Every host built by Host.CreateDefaultBuilder, WebApplication.CreateBuilder or WebApplicationFactory watches appsettings.json and opens one inotify instance for it. A test suite that builds a host per test reaches 128 quickly (sillsdev/serval #1077):
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. at System.IO.FileSystemWatcher.StartRaisingEvents() at Microsoft.Extensions.FileProviders.PhysicalFileProvider.Watch(String filter) ... at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateHost(IHostBuilder builder)
The reporter of #15108 went from green on 24.04 to 187 of 389 tests failing on 26.04. Besides the step above, you can stop test hosts from watching their config at all. fingerprintjs/dotnet-sdk #221 sets the variable in a module initializer of the test assembly, and its ubuntu-latest jobs pass on .NET 8, 9 and 10:
[ModuleInitializer]
internal static void DisableConfigReloadOnChange() =>
Environment.SetEnvironmentVariable("DOTNET_hostBuilder__reloadConfigOnChange", "false");
It is an environment variable because WebApplication.CreateBuilder reads it before ConfigureWebHost runs (mgasca/calendar #31: 153 of 153 pass with the limit at 128). This also makes the tests independent of the runner's limit.
kind, k3s and other clusters: "too many open files"
inotify limits are not namespaced, so every node container and every pod of a cluster in Docker draws from the runner's 128. Pods crash at startup, and the tests time out waiting for them. The messages come from whatever opens the watcher:
- Tekton on kind:
failed to create fsnotify watcher: too many open files(tektoncd/cli #3393) - Falco on kind:
couldn't initialize inotify: too many open files, most often in mTLS jobs, whose sidecars open extra certificate watchers (falco-operator #470) - k3s: "failed to create image import watcher" with "too many open files" (gcpemu #899)
- .NET apps inside the cluster crash with the message from the section above (dapr #10931)
All four raise the limits on the runner before the cluster is created; the limit is the runner kernel's, so the step above goes in the job, ahead of the cluster setup. kind lists the same fix among its known issues. Loading images into kind can fail on 26.04 too: kind load docker-image on Ubuntu 26.04.
ThreadSanitizer: "unexpected memory mapping"
With 32 bits of mmap randomization, ThreadSanitizer runtimes that cannot handle it abort before the program starts. From a TSan-built protoc during CMake configure (valkey-search #1615):
FATAL: ThreadSanitizer: unexpected memory mapping 0x5d2e629f1000-0x5d2e62a20000
Newer runtimes try to restart the program with ASLR turned off. Inside a container that may not be allowed, and they stop with a different message (python-pillow/docker-images #292):
FATAL: ThreadSanitizer: encountered an incompatible memory layout but was unable to disable ASLR (perhaps sandboxing is enabled?). FATAL: Please rerun with lower ASLR entropy, ASLR disabled, and/or sandboxing disabled.
Both projects set vm.mmap_rnd_bits=28, the value 24.04 had, on the runner. A container shares the runner's kernel, so run sudo sysctl on the runner before docker run, not inside the container. valkey-search notes that GCC 13 and 14 have the old runtime and GCC 15's re-executes, so on a newer toolchain the step may become unnecessary (valkey-search #1619). On the runner itself, not in a container, setarch "$(uname -m)" -R runs a single command with ASLR off.
Telling it apart
cat /proc/sys/fs/inotify/max_user_instancesprints 128 on the affected 26.04 images and 1280 on 24.04.sysctl vm.mmap_rnd_bitsprints 32 or 28.- Look at "Set up job": the Runner Image group says
ubuntu-26.04orubuntu-24.04. Until November 19 a re-run can land on 24.04 and pass, so a green re-run proves nothing.runs-on: ubuntu-24.04holds until GitHub retires that image. - A "too many open files" that stays after the step may be a different limit: the open file descriptors of one process (
ulimit -n), not inotify.
Other 26.04 failures
- "client version ... is too old" on Ubuntu 26.04: Docker 29 refuses clients below API 1.40, so older Testcontainers fails with "Could not find a valid Docker environment".
- kind load docker-image on Ubuntu 26.04: Docker 29's containerd image store keeps one platform of a pulled image, so kind's import fails with "ctr: content digest ... not found".
- bubblewrap on Ubuntu 26.04: a sandbox inside
bwrapfails under AppArmor'sbwrap-userns-restrict. - "coreutils: unknown program": most core tools are uutils.
- sudo -E on Ubuntu 26.04:
sudois sudo-rs, which ignores-E. - apt on Ubuntu 26.04: renamed and removed packages.
See failed jobs from IntelliJ IDEA
Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).
GitHub and GitHub Actions are trademarks of GitHub, Inc.; Ubuntu is a trademark of Canonical Ltd.; .NET is a trademark of Microsoft Corporation; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc., Canonical, Microsoft or JetBrains.
More: "The ubuntu-latest label will migrate to Ubuntu 26" · bubblewrap on Ubuntu 26.04 · "coreutils: unknown program" · GitHub Actions plugins for IntelliJ IDEA compared · 日本語