theonedev/onedev · error · ExplicitException

Workspace server not found

Error message

Workspace server not found

What it means

Thrown by DefaultWorkspaceService.openShell() when workspaceServers has no entry for the workspace id. In a cluster, a running workspace lives on exactly one server; that mapping is missing, so the shell request cannot be routed. This means the workspace is not running (or its server registration was lost), not that the workspace entity is absent.

Source

Thrown at server-core/src/main/java/io/onedev/server/workspace/DefaultWorkspaceService.java:854

		update(workspace);
		logService.flush(workspace.getLoggingSupport());
		listenerRegistry.post(new WorkspaceInactive(workspace));
	}

	@Override
	public File getLogFile(Long projectId, Long workspaceNumber) {
		var logDir = projectService.getSubDir(projectId, WORKSPACE_LOGS_DIR);
		return new File(logDir, workspaceNumber.toString());
	}

	@Sessional
	@Override
	public String openShell(Workspace workspace, String label, @Nullable String command,
							 @Nullable ShellOutputCallback outputCallback) {
		var workspaceId = workspace.getId();
		var server = workspaceServers.get(workspaceId);
		if (server == null)
			throw new ExplicitException("Workspace server not found");
		var shellId = clusterService.runOnServer(server, new ClusterTask<String>() {

			@Override
			public String call() throws Exception {
				var runtime = workspaceRuntimes.get(workspaceId);
				if (runtime == null)
					throw new ExplicitException("Workspace runtime not found");
				var shellIdRef = new AtomicReference<String>(null);
				var shellReady = new CompletableFuture<String>();
				var firstOutputSeen = new AtomicBoolean(false);
				shellIdRef.set(runtime.openShell(new Terminal() {

					@Override
					public void onShellOutput(String base64Data) {
						var shellId = shellIdRef.get();
						if (shellId != null) {
							// Use runOnAllServers instead of submitToAllServers to preserve output order
							clusterService.runOnAllServers(newHandleShellOutputTask(workspaceId, shellId, base64Data));

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check the workspace is running and retry after it reaches running state.
  2. Stop and recreate/restart the workspace to rebuild the server mapping.
  3. Verify cluster health — re-register the workspace server if the node was restarted.
  4. Guard the UI/action so shell access is only offered for running workspaces.

Example fix

// before
String shellId = workspaceService.openShell(workspace, "term", null, cb);
// after
if (workspace.getStatus() == WorkspaceStatus.RUNNING) {
    String shellId = workspaceService.openShell(workspace, "term", null, cb);
} else {
    throw new ExplicitException("Workspace is not running");
}
Defensive patterns

Strategy: validation

Validate before calling

// Java
if (workspace.getStatus() != WorkspaceStatus.RUNNING)
    throw new ExplicitException("Workspace must be running to open a shell");

Try / catch

try { workspaceService.openShell(workspace, label, null, cb); } catch (ExplicitException e) { if (e.getMessage().contains("server not found")) restartWorkspace(workspace); }

Prevention

When it happens

Trigger: Calling workspaceService.openShell(workspace, label, command, callback) while the workspace has no active server assignment — e.g. workspace stopped, server restarted, or cluster state desynchronized.

Common situations: Opening a terminal for a workspace that already terminated; a cluster failover removed the server mapping; calling openShell from a node different from the one hosting the workspace without routing; stale UI tab pointing at a dead workspace.

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


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/5b070a38c7e33250. Report an issue: GitHub.