theonedev/onedev · error · ExplicitException
Job shell not ready
Error message
Job shell not ready
What it means
Thrown by DefaultJobService.openShell when a terminal session is opened for a running build, but on the cluster server that owns the job server, no JobRunnable is registered for the job token. It means the build's executing process is not (yet or anymore) able to host an interactive shell. The library throws it as an ExplicitException so the UI shows the message directly.
Source
Thrown at server-core/src/main/java/io/onedev/server/job/DefaultJobService.java:953
}
}
@Sessional
@Override
public JobShell openShell(Build build, JobTerminal terminal) {
var jobContext = getJobContext(build.getId());
if (jobContext != null) {
var jobToken = jobContext.getJobToken();
var shellServer = jobServers.get(jobToken);
if (shellServer != null) {
clusterService.runOnServer(shellServer, () -> {
var innerJobContext = getJobContext(jobToken, true);
var jobRunnable = jobRunnables.get(innerJobContext.getJobToken());
if (jobRunnable != null) {
var shell = jobRunnable.openShell(innerJobContext, terminal);
jobShells.put(terminal.getSessionId(), shell);
} else {
throw new ExplicitException("Job shell not ready");
}
return null;
});
return new JobShell(build.getId(), terminal.getSessionId()) {
private static final long serialVersionUID = 1L;
@Override
public void writeToStdin(String data) {
clusterService.runOnServer(shellServer, () -> {
try {
var shell = jobShells.get(terminal.getSessionId());
if (shell != null)
shell.writeToStdin(data);
} catch (Throwable e) {
logException("Error sending shell input", e);
}View on GitHub (pinned to d44925c47c)
Solutions
- Wait until the build reaches a running state with an active step, then retry opening the terminal
- Refresh the build page and reopen the terminal (stale JobContext/jobServer entries may be gone)
- Check the job executor/logs to confirm the job process is actually alive
- If using a cluster, verify the node hosting the job is healthy
Example fix
// before: opening shell immediately after clicking build
var shell = jobService.openShell(build, terminal);
// after: only open when build is running
if (build.getStatus() == BuildStatus.RUNNING)
var shell = jobService.openShell(build, terminal);
else
throw new IllegalStateException("Build is not running; terminal unavailable"); Defensive patterns
Strategy: retry
Validate before calling
// only attempt terminal when build is actively running
if (build.getStatus() != BuildStatus.RUNNING)
throw new IllegalStateException("Terminal requires a running build"); Type guard
boolean shellAvailable = build.getStatus() == BuildStatus.RUNNING;
Try / catch
try {
var shell = jobService.openShell(build, terminal);
} catch (ExplicitException e) {
// show 'terminal not ready, retry shortly' message
} Prevention
- Only surface the terminal button for RUNNING builds
- Retry after a short delay for builds that just started
- Monitor executor health in clustered setups
When it happens
Trigger: Calling openShell(build, terminal) (e.g. user clicks the terminal button on a build) when jobRunnables.get(jobToken) returns null on the shell server — typically in the window between job server registration and job runnable start, or after the job executor process died.
Common situations: Clicking 'Open terminal' right as the build starts or finishes; the job runner container crashed; build is queued/pending but a stale JobContext still exists; multi-node cluster race where the shell server differs from the running node.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Allocated agent not connected to current server, please retr
- Attachment not found:
- Malformed build spec
- This build is not authorized to sync to project:
- Loopback address not allowed for target docker image of push
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/26c06872776820f3.
Report an issue: GitHub.