coleam00/Archon · error · Error

Detached work stopped, but cancellation did not win the run

Error message

Detached work stopped, but cancellation did not win the run state transition. The run status is ${latest?.status ?? 'unknown'}; it was not reported as cancelled.

What it means

After stopping the detached owner process, the CLI calls `abandonWorkflow(resolvedId)` to win the run-state transition to `cancelled`. If it reports `cancelled: false`, another actor changed the run state concurrently; the CLI re-reads the run and reports the actual status instead of falsely claiming a successful cancel.

Source

Thrown at packages/cli/src/commands/workflow.ts:4437

    const target = await requestDetachedRunStop(resolvedId);
    await target.stop();

    if (containerEnvId) {
      try {
        await reclaimContainerEnv(containerEnvId);
      } catch (error) {
        throw new Error(
          'Detached owner process stopped, but the isolation container could not be confirmed stopped. ' +
            `Run state was not changed. ${(error as Error).message}`
        );
      }
    }

    const { run, cancelled, cascadeFailures, blockedParentRunId } =
      await abandonWorkflow(resolvedId);
    if (!cancelled) {
      const latest = await workflowDb.getWorkflowRun(resolvedId);
      throw new Error(
        'Detached work stopped, but cancellation did not win the run state transition. ' +
          `The run status is ${latest?.status ?? 'unknown'}; it was not reported as cancelled.`
      );
    }
    return {
      resolvedId,
      workflowName: run.workflow_name,
      cascadeFailures,
      blockedParentRunId,
    };
  };

  if (json) {
    try {
      const result = await cancel();
      await writeJsonLine({
        ok: true,
        runId: result.resolvedId,

View on GitHub (pinned to 0773b97458)

Solutions

  1. Re-check the run status (`archon workflow status <id>`); if it is completed/failed, the outcome is fine and no cancel was needed
  2. If still running, retry the cancel once the concurrent operation settles
  3. Ensure only one operator/process issues control commands for a given run

Example fix

// before
await cancelWorkflow(runId); // may throw on lost race
// after
try { await cancelWorkflow(runId); }
catch (e) {
  const run = await getWorkflowRun(runId);
  if (run.status === 'completed') console.log('run already finished; cancel not needed');
  else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

const run = await workflowDb.getWorkflowRun(id);
if (run.status !== 'running') { console.log(`run is ${run.status}; nothing to cancel`); return; }

Try / catch

try {
  await cancelWorkflow(id);
} catch (e) {
  if (String(e).includes('did not win the run state transition')) {
    const latest = await workflowDb.getWorkflowRun(id);
    if (latest?.status === 'running') await cancelWorkflow(id); // retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `archon workflow cancel` while another process (another cancel, an engine transition, a completion) concurrently moves the run out of `running`, so the abandon transition loses the race.

Common situations: Two operators cancelling the same run simultaneously; the run finishing naturally between process-stop and state transition; an engine watchdog or resume operation touching the run concurrently.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/dd6b0fbc69e1e909. Report an issue: GitHub.