jenkinsci/jenkins · error · IOException

jenkins.war location is not known.

Error message

jenkins.war location is not known.

What it means

Thrown by Lifecycle.rewriteHudsonWar(File) when getHudsonWar() returns null. This base implementation is used to overwrite jenkins.war during an in-place upgrade. A null war path means Jenkins could not determine where its own war file lives. The code comment notes this should be impossible if canRewriteHudsonWar() was honored, hence it is a defensive guard.

Source

Thrown at core/src/main/java/hudson/lifecycle/Lifecycle.java:169

        String war = SystemProperties.getString("executable-war");
        if (war != null && new File(war).exists())
            return new File(war);
        return null;
    }

    /**
     * Replaces jenkins.war by the given file.
     *
     * <p>
     * On some system, most notably Windows, a file being in use cannot be changed,
     * so rewriting {@code jenkins.war} requires some special trick. Override this method
     * to do so.
     */
    public void rewriteHudsonWar(File by) throws IOException {
        File dest = getHudsonWar();
        // this should be impossible given the canRewriteHudsonWar method,
        // but let's be defensive
        if (dest == null)  throw new IOException("jenkins.war location is not known.");

        // backing up the old jenkins.war before it gets lost due to upgrading
        // (newly downloaded jenkins.war and 'backup' (jenkins.war.tmp) are the same files
        // unless we are trying to rewrite jenkins.war by a backup itself
        File bak = new File(dest.getPath() + ".bak");
        if (!by.equals(bak))
            FileUtils.copyFile(dest, bak);

        FileUtils.copyFile(by, dest);
        // we don't want to keep backup if we are downgrading
        if (by.equals(bak)) {
            Files.deleteIfExists(Util.fileToPath(bak));
        }
    }

    /**
     * Can {@link #rewriteHudsonWar(File)} work?
     */

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Run Jenkins from the actual jenkins.war file so the war location is resolvable
  2. If using a servlet container, perform upgrades by redeploying the war via the container, not via Jenkins' restart API
  3. Check that the war location system property / launch argument is set correctly
  4. Avoid calling the in-place upgrade API in environments without a physical war file
Defensive patterns

Strategy: validation

Validate before calling

Lifecycle lc = Lifecycle.get();
if (lc.getHudsonWar() == null) {
    throw new IllegalStateException("No jenkins.war location; in-place upgrade is not available in this mode");
}

Try / catch

try {
    Lifecycle.get().rewriteHudsonWar(newWar);
} catch (IOException e) {
    if (e.getMessage().contains("jenkins.war location is not known")) {
        // cannot do in-place upgrade here; redeploy externally
    }
    throw e;
}

Prevention

When it happens

Trigger: An upgrade or downgrade path calls rewriteHudsonWar(by); getHudsonWar() returns null because the war location was never set (e.g. launched from an exploded classpath or a custom main that does not set the war file).

Common situations: Running Jenkins from an IDE or exploded webapp where there is no jenkins.war on disk; deploying under a servlet container (Tomcat) where the war identity differs; a custom launcher that does not populate the war location.

Related errors


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/564fbe8e2ea78459. Report an issue: GitHub.