Which Jenkins LTS lines can go straight to 2.580.1

Rehearsed 2026-10-21 · 38 LTS lines · 100 and 300 plugins · 328 Jenkins starts

Short answer. If your controller is on 2.401.3 or newer, replacing only the war, the package or the image with 2.580.1 loaded all of the 300 most installed plugins. On 2.346.3 or older it never did, with or without network access: plugins failed to load, and with 300 plugins 12 of those 21 lines did not start at all. Going in steps, through 2.346.3, 2.462.3 and 2.541.3 and changing Java on the way, loaded every plugin from every line. 2.580.1 needs Java 21, on the controller and on the agents.

New in 2.580.1. Jenkins 2.574 and 2.577 took the plugins that were split out of core out of the war. Before, an upgraded controller installed the ones it was missing from its own war. Jenkins does not download them when it starts, so a controller older than 2.356 comes up on 2.580.1 without instance-identity, and older ones also without sshd and the JavaMail plugins. This happens even when the update center is reachable: we repeated the upgrade from 2.346.3 and 2.277.4 with network access and got the same failure. If yours is on 2.356 or older, upgrade to an LTS that still bundles them (2.568.3 or earlier) first, update your plugins there, and only then go to 2.580.1. Copying in instance-identity alone is not enough: it needs a newer bouncycastle-api too.

How we tested

What we found

300 most installed plugins

FromControllersBefore the upgradeCore only → 2.580.1StepsAfter the steps
2.60.3<0.1%✅ all load⚠️ 9 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.73.3<0.1%✅ all load⚠️ 9 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.89.4<0.1%✅ all load⚠️ 121 fail, 10 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.107.3<0.1%✅ all load⚠️ 121 fail, 10 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.121.30.1%✅ all load⚠️ 122 fail, 9 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.138.40.2%✅ all load⚠️ 126 fail, 7 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.150.30.2%✅ all load⚠️ 127 fail, 7 load partly2.346.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.164.30.3%✅ all load❌ does not start (1 fail, 10 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.176.40.4%✅ all load❌ does not start (1 fail, 9 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.190.30.4%✅ all load❌ does not start (8 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.204.60.4%✅ all load❌ does not start (8 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.222.40.5%✅ all load❌ does not start (8 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.235.50.5%✅ all load❌ does not start (7 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.249.30.5%✅ all load❌ does not start (7 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.263.40.7%✅ all load❌ does not start (4 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.277.40.5%✅ all load❌ does not start (4 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.289.30.7%⚠️ 97 fail⚠️ 97 fail, 1 load partly2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.303.30.7%⚠️ 98 fail⚠️ 98 fail, 1 load partly2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.319.30.9%✅ all load❌ does not start (2 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.332.41.4%✅ all load❌ does not start (2 load partly)2.462.3 (Java 11) → 2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.346.32.2%✅ all load❌ does not start (2 load partly)2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.361.40.7%⚠️ 1 load partly⚠️ 1 load partly2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.375.40.8%⚠️ 1 load partly⚠️ 1 load partly2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.387.31.3%⚠️ 1 load partly⚠️ 1 load partly2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.401.31.0%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.414.31.2%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.426.32.6%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.440.32.1%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.452.42.2%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.462.33.7%✅ all load✅ all load2.541.3 (Java 17) → 2.580.1 (Java 21)✅ all load
2.479.33.5%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.492.34.2%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.504.34.7%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.516.35.7%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.528.311.6%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.541.323.2%✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.555.3–✅ all load✅ all load2.580.1 (Java 21)✅ all load
2.568.3–✅ all load✅ all load2.580.1 (Java 21)✅ all load

100 most installed plugins

From 2.361.4 on, all 100 loaded before the upgrade, after a core-only upgrade and after the steps. The lines before it:

FromControllersBefore the upgradeCore only → 2.580.1After the steps
2.60.3<0.1%✅ all load⚠️ 6 load partly✅ all load
2.73.3<0.1%✅ all load⚠️ 6 load partly✅ all load
2.89.4<0.1%✅ all load⚠️ 42 fail, 4 load partly✅ all load
2.107.3<0.1%✅ all load⚠️ 42 fail, 4 load partly✅ all load
2.121.30.1%✅ all load⚠️ 44 fail, 4 load partly✅ all load
2.138.40.2%✅ all load⚠️ 44 fail, 3 load partly✅ all load
2.150.30.2%✅ all load⚠️ 45 fail, 3 load partly✅ all load
2.164.30.3%✅ all load⚠️ 2 fail, 6 load partly✅ all load
2.176.40.4%✅ all load⚠️ 2 fail, 6 load partly✅ all load
2.190.30.4%✅ all load⚠️ 5 load partly✅ all load
2.204.60.4%✅ all load⚠️ 5 load partly✅ all load
2.222.40.5%✅ all load⚠️ 5 load partly✅ all load
2.235.50.5%✅ all load⚠️ 4 load partly✅ all load
2.249.30.5%✅ all load⚠️ 4 load partly✅ all load
2.263.40.7%✅ all load⚠️ 2 load partly✅ all load
2.277.40.5%✅ all load⚠️ 2 load partly✅ all load
2.289.30.7%⚠️ 30 fail⚠️ 30 fail✅ all load
2.303.30.7%⚠️ 31 fail⚠️ 31 fail✅ all load
2.319.30.9%✅ all load⚠️ 2 load partly✅ all load
2.332.41.4%✅ all load⚠️ 2 load partly✅ all load
2.346.32.2%✅ all load⚠️ 2 load partly✅ all load

What this does not cover

Use the data

The rows behind both tables are published as JSON: matrix.json, one row per starting line and plugin count (76 rows). Each row has the starting core, the result of replacing only the core (asIs), and the stops of the tested path in order, each with its core and the java it ran on.

If an AI agent is upgrading your controller, give it that file. Ask it to take the row for your LTS line and to go through its stops in order: switch the controller and every agent to the stop's java, upgrade the core to the stop's core, and update every plugin before going on to the next stop. Use java, not planJava: java is what the rehearsal needed, and it is newer where a plugin required it: from 2.150.3 or older, the gradle plugin needs Java 11 at the 2.346.3 stop, where the plan alone says Java 8.

Your own plugin list

Run this in Manage Jenkins → Script Console and send the output to hello@keelinfra.io:

Jenkins.instance.pluginManager.plugins.sort { it.shortName }.each { println "${it.shortName}:${it.version}" }

We run the same rehearsal with your plugins and your target version, and reply in writing: which stops your upgrade needs, which Java each one runs on, which plugins fail at which stop, and which split-out plugins it is missing. This is free: real plugin lists are how we test the rehearsal.

Or run it yourself: the table was made with jenkins-upgrade-check, which plans the stops for your plugin list, rehearses each one in a container, and after the real upgrade says whether to keep it or roll back.