coleam00/Archon · error

Run ${run.id} is paused waiting on sub-run ${attention.child

Error message

Run ${run.id} is paused waiting on sub-run ${attention.childRunId} ('workflow:' node '${attention.nodeId}'). Reject the child run instead: /workflow reject ${attention.childRunId} To discard the whole tree, abandon this run.

What it means

When a paused parent run is blocked waiting on a child sub-run ('blocked_on_child'), its pause is not a rejectable approval gate. Rejecting the parent would orphan the still-paused child, so the library redirects the caller to reject the child run (its actual gate) or abandon the parent to cascade-cancel the whole subtree.

Source

Thrown at packages/core/src/operations/workflow-operations.ts:349

 */
export function assertRejectable(run: WorkflowRun): ApprovalContext | undefined {
  if (run.status !== 'paused') {
    throw new Error(
      `Cannot reject run with status '${run.status}'. Only paused runs can be rejected.`
    );
  }
  const rawApproval = run.metadata.approval;
  const approval: ApprovalContext | undefined = isApprovalContext(rawApproval)
    ? rawApproval
    : undefined;
  const attention = runAttention(run);
  switch (attention?.kind) {
    case 'blocked_on_child':
      // Same redirect as assertApprovable: the parent's pause is not a rejectable
      // gate — cancelling the parent here would silently orphan the still-paused
      // child run. Reject the child (its own gate) or abandon the parent (which
      // cascade-cancels the subtree) instead.
      throw new Error(
        `Run ${run.id} is paused waiting on sub-run ${attention.childRunId} ` +
          `('workflow:' node '${attention.nodeId}'). Reject the child run instead` +
          `: /workflow reject ${attention.childRunId}` +
          ' To discard the whole tree, abandon this run.'
      );
    case 'unreadable':
      // The one deliberate divergence from approve: unreadable gate METADATA is
      // still rejectable (see this function's doc comment). An unrecognized gate
      // TYPE is not, and neither is a block pointer with nothing to follow.
      if (attention.reason === 'malformed_gate') break;
      throw new Error(unreadableGateMessage(run, attention, approval));
    case undefined:
      if (approval && isGateResolved(approval)) {
        throw new Error(
          `Workflow run ${run.id} was already ${String(approval.resolved)} and is awaiting resume.`
        );
      }
      break;

View on GitHub (pinned to 0773b97458)

Solutions

  1. Reject the child run instead: run '/workflow reject <attention.childRunId>' on the sub-run named in the message.
  2. If the whole tree should be discarded, abandon the parent run — cascade-cancel will tear down the subtree.
  3. Inspect run metadata's attention/block pointer before rejecting to detect 'blocked_on_child' parents.

Example fix

// before
await workflowRejectCommand({ runId: parentId });
// after
const childId = run.metadata?.approval?.attention?.childRunId;
if (childId) {
  await workflowRejectCommand({ runId: childId }); // reject the actual gate
} else {
  await abandonWorkflow(parentId); // discard whole tree
}
Defensive patterns

Strategy: validation

Validate before calling

const attention = run.metadata?.approval?.attention;
if (attention?.kind === 'blocked_on_child') {
  // redirect to child
}

Type guard

function isBlockedOnChild(a: unknown): a is { kind: 'blocked_on_child'; childRunId: string; nodeId: string } {
  return !!a && typeof a === 'object' && (a as any).kind === 'blocked_on_child';
}

Try / catch

try { await workflowRejectCommand({ runId: parent.id }); }
catch (e) {
  const m = /waiting on sub-run (\S+)/.exec((e as Error).message);
  if (m) await workflowRejectCommand({ runId: m[1] }); // reject child
  else throw e;
}

Prevention

When it happens

Trigger: Calling workflowRejectCommand on a parent run whose metadata block pointer has attention.kind === 'blocked_on_child' — i.e. the run was paused by a 'workflow:' node delegating to a sub-run that itself sits at a gate.

Common situations: An operator lists paused runs, picks the parent of a sub-workflow tree, and tries to reject it; a bot command hits the wrong ID in a parent/child chain; someone wants to unwind a multi-run workflow but addresses the root instead of the leaf gate.

Related errors


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