jenkinsci/jenkins · error · IllegalStateException

Cannot build {0} for unknown reasons.

Error message

Cannot build {0} for unknown reasons.

What it means

Thrown as an IllegalStateException when job.isBuildable() returns false and neither the disabled-check (not a ParameterizedJob or not disabled) nor the hold-off-check (isHoldOffBuildUntilSave is false) matches. The message comes from Messages.BuildCommand_CLICause_CannotBuildUnknownReasons with the job's full display name.

Source

Thrown at core/src/main/java/hudson/cli/BuildCommand.java:164

            SCMTriggerItem item = SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(job);
            if (item == null)
                throw new AbortException(job.getFullDisplayName() + " has no SCM trigger, but checkSCM was specified");
            // preemptively check for a polling veto
            if (SCMDecisionHandler.firstShouldPollVeto(job) != null) {
                return 0;
            }
            if (!item.poll(new StreamTaskListener(stdout, getClientCharset())).hasChanges())
                return 0;
        }

        if (!job.isBuildable()) {
            String msg = Messages.BuildCommand_CLICause_CannotBuildUnknownReasons(job.getFullDisplayName());
            if (job instanceof ParameterizedJobMixIn.ParameterizedJob && ((ParameterizedJobMixIn.ParameterizedJob) job).isDisabled()) {
                msg = Messages.BuildCommand_CLICause_CannotBuildDisabled(job.getFullDisplayName());
            } else if (job.isHoldOffBuildUntilSave()) {
                msg = Messages.BuildCommand_CLICause_CannotBuildConfigNotSaved(job.getFullDisplayName());
            }
            throw new IllegalStateException(msg);
        }

        Queue.Item item = ParameterizedJobMixIn.scheduleBuild2(job, 0, new CauseAction(new CLICause(Jenkins.getAuthentication2().getName())), a);
        QueueTaskFuture<? extends Run<?, ?>> f = item != null ? (QueueTaskFuture) item.getFuture() : null;

        if (wait || sync || follow) {
            if (f == null) {
                throw new IllegalStateException(BUILD_SCHEDULING_REFUSED);
            }
            Run<?, ?> b = f.waitForStart();    // wait for the start
            stdout.println("Started " + b.getFullDisplayName());
            stdout.flush();

            if (sync || follow) {
                try {
                    if (consoleOutput) {
                        // read output in a retry loop, by default try only once
                        // writeWholeLogTo may fail with FileNotFound

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Check for extensions that may block building: search for implementations of Queue.QueueDecisionHandler or similar veto mechanisms.
  2. Restart Jenkins to clear any transient non-buildable state.
  3. Check the job's configuration for any plugin that might be marking it as non-buildable.
  4. If the job is a custom type, verify its isBuildable() implementation.
Defensive patterns

Strategy: validation

Validate before calling

// Check buildability with specific reason detection
if (!job.isBuildable()) {
    if (job instanceof ParameterizedJobMixIn.ParameterizedJob
            && ((ParameterizedJobMixIn.ParameterizedJob) job).isDisabled()) {
        throw new AbortException(job.getFullDisplayName() + " is disabled. Enable it first.");
    } else if (job.isHoldOffBuildUntilSave()) {
        throw new AbortException(job.getFullDisplayName() + " configuration has not been saved.");
    } else {
        throw new AbortException(job.getFullDisplayName() + " is not buildable for an unknown reason. Check extensions and job type.");
    }
}

Type guard

public static boolean isBuildable(Job<?, ?> job) {
    return job.isBuildable();
}

Try / catch

try {
    // build command run()
} catch (IllegalStateException e) {
    stderr.println(e.getMessage());
    stderr.println("Check for build-blocking extensions or restart Jenkins.");
    return 1;
}

Prevention

When it happens

Trigger: job.isBuildable() is false, the job is not an instance of ParameterizedJobMixIn.ParameterizedJob (or is but isDisabled() returns false), and job.isHoldOffBuildUntilSave() returns false — meaning the job is non-buildable for some other reason not covered by the two checked conditions.

Common situations: A Queue.QueueDecisionHandler or similar extension is blocking builds; the job is in a transient state after a restart; a plugin's Job implementation overrides isBuildable() to return false under custom conditions; the job type does not extend ParameterizedJobMixIn and is not in a hold-off state.

Related errors


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