theonedev/onedev · error · ExplicitException

This workspace is provisioned on server previously, and…

Error message

This workspace is provisioned on server previously, and cannot be reprovisioned via %s

What it means

AgentProvisionerUtils.submitTask refuses to provision a workspace that was previously provisioned on the server itself when the current request pins a remote target (pinnedServerAddress set), e.g. reprovisioning via a build runner/executor on an agent. The workspace's server affinity cannot be changed by remote provisioning.

Solutions

  1. Delete the existing workspace cache so the next run provisions on the target (agent or current server).
  2. Change the job/runner config so it runs on the server as before, matching the workspace's original provisioning.
  3. Clear stale workspace caches on the server (Administration > Workspace Caches or project workspace cache cleanup) after changing executor assignment.
Defensive patterns

Strategy: try-catch

Try / catch

try { provision(...); } catch (ExplicitException e) { if (e.getMessage().contains("cannot be reprovisioned")) { clearWorkspaceCache(); retryOnTarget(); } }

Prevention

When it happens

Trigger: A job/step targets an agent (serverUrl/agent pinned via resourceName or runner settings) but the workspace cache was originally provisioned on the OneDev server; submitTask is then called with pinnedServerAddress != null.

Common situations: Moving a job between server-executed and agent-executed runners without clearing the workspace; reusing a project/workspace cache created by server-side builds; cluster setups where agents should run jobs but old workspaces linger.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at server-core/src/main/java/io/onedev/server/workspace/AgentProvisionerUtils.java:37

import io.onedev.server.search.entity.agent.AgentQuery;
import io.onedev.server.service.AgentService;
import io.onedev.server.service.ResourceService;

public final class AgentProvisionerUtils {

	private static final Logger logger = LoggerFactory.getLogger(AgentProvisionerUtils.class);

	private static final ThreadLocal<Long> ALLOCATED_AGENT = new ThreadLocal<>();

	public static Long getAllocatedAgent() {
		return ALLOCATED_AGENT.get();
	}

	public static <T> Future<T> submitTask(@Nullable String pinnedServerAddress, @Nullable Long pinnedAgentId,
			@Nullable String agentQuery, String resourceName, int concurrency,
			String cannotReprovisionVia, ClusterTask<T> task, TaskLogger logger) {
		if (pinnedServerAddress != null) {
			throw new ExplicitException(String.format("""
				This workspace is provisioned on server previously, \
				and cannot be reprovisioned via %s""", cannotReprovisionVia));
		}

		logger.log("Pending resource allocation...");
		return getResourceService().submitAgentTask(
				pinnedAgentId,
				AgentQuery.parse(agentQuery, true),
				resourceName,
				concurrency, 1,
				agentId -> {
					ALLOCATED_AGENT.set(agentId);
					try {
						return task.call();
					} catch (Exception e) {
						throw ExceptionUtils.unchecked(e);
					} finally {
						ALLOCATED_AGENT.remove();

View on GitHub (pinned to d44925c47c)