jenkinsci/jenkins · error · IllegalStateException

Permalink produced no build

Error message

Permalink  produced no build

What it means

In `ConsoleCommand.run()`, when BUILD is not numeric (NumberFormatException is caught) but IS a recognized permalink (`job.getPermalinks().get(build)` non-null), the code calls `p.resolve(job)`. If resolve returns null (the permalink exists but points to no run, e.g. 'lastSuccessfulBuild' on a job with no successful build), it throws IllegalStateException 'Permalink <build> produced no build'. The original NumberFormatException is chained as the cause.

Source

Thrown at core/src/main/java/hudson/cli/ConsoleCommand.java:59

    @Override
    protected int run() throws Exception {
        job.checkPermission(Item.READ);

        Run<?, ?> run;

        try {
            int n = Integer.parseInt(build);
            run = job.getBuildByNumber(n);
            if (run == null)
                throw new IllegalArgumentException("No such build #" + n);
        } catch (NumberFormatException e) {
            // maybe a permalink?
            Permalink p = job.getPermalinks().get(build);
            if (p != null) {
                run = p.resolve(job);
                if (run == null)
                    throw new IllegalStateException("Permalink " + build + " produced no build", e);
            } else {
                Permalink nearest = job.getPermalinks().findNearest(build);
                throw new IllegalArgumentException(nearest == null ?
                        String.format("Not sure what you meant by \"%s\".", build) :
                        String.format("Not sure what you meant by \"%s\". Did you mean \"%s\"?",
                                build, nearest.getId()), e);
            }
        }

        OutputStreamWriter w = new OutputStreamWriter(stdout, getClientCharset());
        try {
            long pos = n >= 0 ? seek(run) : 0;

            if (follow) {
                AnnotatedLargeText logText;
                do {
                    logText = run.getLogText();
                    pos = logText.writeLogTo(pos, w);

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Trigger a build that satisfies the permalink first (e.g. obtain a successful build before requesting lastSuccessfulBuild).
  2. Use a concrete build number or `lastBuild` (resolves to the most recent run regardless of result) instead of a result-filtered permalink.
  3. Check `job.getPermalinks()` resolution in a script before invoking the CLI, and fall back to lastBuild when null.

Example fix

// before: no successful build exists yet
//   java -jar jenkins-cli.jar console myjob lastSuccessfulBuild
//   -> IllegalStateException: Permalink lastSuccessfulBuild produced no build
//
// after: use lastBuild (always present) or a concrete build number
//   java -jar jenkins-cli.jar console myjob lastBuild
Defensive patterns

Strategy: validation

Validate before calling

// When using a permalink, resolve it first and fall back gracefully
Permalink p = job.getPermalinks().get(buildArg);
if (p != null) {
    Run<?, ?> r = p.resolve(job);
    if (r == null) {
        // no qualifying build yet; use lastBuild instead
        buildArg = "lastBuild";
    }
}

Prevention

When it happens

Trigger: Running `java -jar jenkins-cli.jar console <job> lastSuccessfulBuild` (or lastStableBuild/lastFailedBuild) when the job has no build matching that permalink yet — e.g. only failed builds exist so lastSuccessfulBuild resolves to null.

Common situations: Querying a new or always-failing job's successful/stable console before any qualifying build exists; permalink corrupted by partial build deletion.

Related errors


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