GitHub Actions Ubuntu 26.04 Migration: What Breaks When ubuntu-latest Moves
GitHub Actions Ubuntu 26.04 Migration: What Breaks When ubuntu-latest Moves
On September 17, 2026, GitHub announced that the ubuntu-latest runner label is moving from Ubuntu 24.04 to Ubuntu 26.04, rolling out gradually between October 19 and November 19, 2026. If your workflows just say runs-on: ubuntu-latest and assume that means "whatever Ubuntu GitHub feels like giving me, it'll be fine" โ it usually has been fine, until it silently isn't. This release moves the default JDK from 17 to 25, drops several tools outright, and jumps Docker Compose, Helm, and CMake across major versions. None of that shows up until a job that worked yesterday fails today, on a runner you didn't choose to change.
Why this matters more than a routine OS bump
GitHub ships a new Ubuntu runner image on essentially every LTS release, and most of the time nobody notices because ubuntu-latest quietly carries you along. What makes this one worth planning for specifically is the size of the jumps inside it โ this isn't a patch-level refresh, it's a runtime-major-version and tool-removal release, and the rollout window is a month-long gradual migration rather than a single cutover, so some of your concurrent CI runs could be on 24.04 and others on 26.04 during that window with no code change on your end.
What actually changes (verified against the official runner-images manifests)
Comparing the published Ubuntu 24.04 and 26.04 runner image manifests directly, here's what moves:
| Component | Ubuntu 24.04 (current) | Ubuntu 26.04 (incoming) |
|---|---|---|
| Java (system default) | 17.0.20 | 25.0.4 |
| Python (system) | 3.12.3 | 3.14.4 |
| Node.js (system) | 22.23.2 | 24.20.0 |
| Ruby (system) | 3.2.3 | 3.3.8 |
| PHP | 8.3.6 | 8.5.4 |
| Docker Client/Server | 28.0.4 | 29.4.2 |
| Docker Compose | 2.38.2 | 5.1.3 |
| Helm | 3.21.4 | 4.2.4 |
| CMake | 3.31.6 | 4.4.3 |
| PostgreSQL | 16.15 | 18.6 |
| MySQL | 8.0.46 | 8.4.11 |
| Podman | 4.9.3 | 5.7.0 |
The Java default jump (17 โ 25) is the one most teams will hit first, since a lot of Maven/Gradle builds don't pin a JDK version explicitly and just trust whatever JAVA_HOME points to. Docker Compose and Helm both cross major version boundaries too, which usually means CLI flag and compose-file schema changes, not just a version string bump.
Tools removed entirely from the 26.04 image
These are present on ubuntu-24.04 and simply absent from ubuntu-26.04 โ if a job depends on them being preinstalled, it will fail with a "command not found" rather than a version mismatch:
- Java 8 โ only 11, 17, 21, and 25 ship now
- Miniconda (the
CONDAenvironment variable is present but empty on 26.04) - Swift
- Julia
- Pulumi
- Fastlane
- Mercurial
- Newman (Postman's CLI runner)
- Parcel
- Lerna
- MediaInfo
- Sphinx Open Source Search Server
Two apt package names also changed: p7zip-full/p7zip-rar become 7zip/7zip-rar, and dnsutils becomes bind9-dnsutils. If a workflow step runs apt-get install -y p7zip-full or dnsutils explicitly, that install step breaks on 26.04 even though the underlying functionality still exists under a new package name.
Step 1: Decide now โ pin, or start testing
You have exactly two responsible options between now and October 19. Doing nothing and hoping isn't one of them, because the rollout is gradual and non-deterministic from your side.
Option A โ pin to the current image if you're not ready:
1jobs:
2 build:
3 runs-on: ubuntu-24.04 # not ubuntu-latest
This freezes you on 24.04 indefinitely (GitHub has not announced an end-of-life date for the 24.04 image alongside this change), buying time to migrate deliberately instead of reactively.
Option B โ test against 26.04 explicitly, right now, before the label moves:
1jobs:
2 build:
3 strategy:
4 fail-fast: false
5 matrix:
6 os: [ubuntu-24.04, ubuntu-26.04]
7 runs-on: ${{ matrix.os }}
8 steps:
9 - uses: actions/checkout@v7
10 - run: ./run-tests.sh
Running both in parallel for a couple of weeks tells you exactly which jobs break on 26.04 while your production pipeline stays safely on 24.04 the whole time. This is the better option for anything you actually intend to keep maintaining โ pinning without a follow-up plan just relocates the surprise to whenever 24.04 eventually does get deprecated (the same pattern already playing out with Ubuntu 22.04, which began deprecating September 17, 2026, four months after this announcement).
Step 2: Stop trusting the system default runtime
The single highest-leverage fix here isn't specific to this migration โ it's the general practice of never relying on whatever language runtime the image happens to default to:
1steps:
2 - uses: actions/setup-java@v4
3 with:
4 distribution: 'temurin'
5 java-version: '17'
6
7 - uses: actions/setup-python@v5
8 with:
9 python-version: '3.12'
10
11 - uses: actions/setup-node@v4
12 with:
13 node-version: '22'
Workflows that pin their runtime with setup-java/setup-python/setup-node don't care what image version ships underneath โ those actions download and cache the exact version you asked for regardless of the runner OS. If your workflows currently skip these actions and just invoke java, python3, or node directly, the Ubuntu 26.04 migration is a good forcing function to add them.
Step 3: Reinstall anything that got removed
For tools dropped from the base image, add an explicit install step rather than assuming it'll still be there:
1- name: Install Miniconda (removed from ubuntu-26.04 base image)
2 run: |
3 curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o miniconda.sh
4 bash miniconda.sh -b -p "$HOME/miniconda"
5 echo "$HOME/miniconda/bin" >> "$GITHUB_PATH"
Same pattern for Pulumi (curl -fsSL https://get.pulumi.com | sh), Fastlane (gem install fastlane), or any other tool that disappeared from the table above.
Best practices
- Never let a production pipeline discover a runner migration for the first time. Run the matrix job from Step 1 well before a vendor's stated rollout window, not after something breaks.
- Pin runtimes with the official
setup-*actions everywhere, not just in workflows you know touch this migration โ it removes an entire category of future "the runner changed under us" incidents. - Audit for hardcoded
apt-get installpackage names in your workflows specifically; renamed packages are the quietest failure mode here because the error message ("Unable to locate package") gives no hint that the real cause is an OS version change. - Check Docker Compose and Helm files for major-version syntax dependencies if you use either tool's CLI directly in CI rather than through a pinned container image.
Common mistakes to avoid
- Assuming
ubuntu-latestis a stable target. It's a moving label by design โ GitHub has changed what it points to before and will again. - Pinning to
ubuntu-24.04and calling it done. That buys time, it doesn't solve the underlying fragility; put the matrix test from Step 1 on the calendar for a follow-up. - Fixing the Java version problem by hardcoding a
JAVA_HOME_25_X64-style path. Those environment variable names are runner-image implementation details, not a stable API โ usesetup-javainstead. - Only testing the main branch's default workflow. Release workflows, nightly builds, and matrix jobs that only run on a schedule are exactly the ones people forget to re-test, and exactly the ones that fail silently for weeks before anyone notices.
Troubleshooting
Job fails with command not found: conda (or pulumi, fastlane, julia, swift). The tool was removed from the 26.04 base image (see the list above) โ add an explicit install step.
apt-get install p7zip-full fails with Unable to locate package. The package was renamed to 7zip on 26.04. Update the package name, or better, install both conditionally based on $ImageOS if you need to support both runner generations during the transition.
Build fails after a Java version bump you didn't request. Your workflow was relying on the system default JDK instead of actions/setup-java. Add the action and pin the exact major version your build targets.
docker compose commands fail with unrecognized flags. Docker Compose jumped from 2.38.2 to 5.1.3 on the new image โ check the CLI reference for flags/subcommands that changed across that range, particularly anything scripted rather than typed interactively.
FAQ
Do I need to do anything if I already pin runs-on: ubuntu-24.04?
No immediate action โ you're insulated from this specific rollout. Just don't treat the pin as permanent; put a reminder on the calendar to test against 26.04 deliberately.
Will ubuntu-24.04 be removed soon?
GitHub hasn't announced a 24.04 end-of-life alongside this change. Ubuntu 22.04-based runner images did begin their deprecation on September 17, 2026 (fully unsupported by April 17, 2027) โ a useful reference point for how much runway a pin typically buys you.
Can I use ubuntu-26.04 today, before the ubuntu-latest migration?
Yes โ it's already out of preview and fully supported. Set runs-on: ubuntu-26.04 (or ubuntu-26.04-arm for Arm64) explicitly to start testing now instead of waiting for the label to move under you.
Does this affect self-hosted runners too?
No โ this only affects GitHub-hosted runners using the ubuntu-latest/ubuntu-24.04/ubuntu-26.04 labels. Self-hosted runners use whatever OS you installed them on, and are governed by a separate runner-version enforcement policy (see the related post below).
Where's the authoritative list of every change, not just the highlights here?
actions/runner-images on GitHub publishes the full software manifest for every image version โ diff the Ubuntu2404-Readme.md and Ubuntu2604-Readme.md files directly for anything not covered above.
Key takeaways
| Question | Answer |
|---|---|
| What's changing? | GitHub Actions' ubuntu-latest label moves from Ubuntu 24.04 to 26.04 |
| When? | Gradual rollout, October 19 โ November 19, 2026 |
| Biggest default-runtime jump? | Java 17 โ 25 |
| Tools removed entirely? | Miniconda, Java 8, Swift, Julia, Pulumi, Fastlane, Mercurial, Newman, Parcel, Lerna, MediaInfo, Sphinx |
| Renamed apt packages? | p7zip-full/p7zip-rar โ 7zip/7zip-rar; dnsutils โ bind9-dnsutils |
| How to stay on the current image? | runs-on: ubuntu-24.04 instead of ubuntu-latest |
| How to test the new image now? | runs-on: ubuntu-26.04, or a matrix of both |
| Best long-term fix? | Pin runtimes explicitly with setup-java/setup-python/setup-node instead of trusting the system default |
Further Reading
- GitHub Actions Self-Hosted Runners: Fix Your Version Before the September 25 Enforcement
- GitHub Actions Checkout v7: Fixing the Pwn Request Vulnerability Before July 16
- Docker Engine 29.8.0: --umask Flag, Custom AppArmor Profiles, and CloudWatch Entity Logging
- Official: Ubuntu 26 generally available and latest migration โ GitHub Changelog
- Official: actions/runner-images software manifests