coleam00/Archon · error

workflow.fan_out_interactive_target

workflow.fan_out_interactive_target

Error message

fan_out node '${node.id}': target workflow '${node.workflow}' is interactive-class ('interactive: true') and may pause for human input — a fan-out has a single approval-gate slot for N children, so this is refused before any child is created. Remove the pause capability from '${node.workflow}', or invoke it as a single (non-fan-out) 'workflow:' node instead.

What it means

Archon's dag-executor refuses to fan out a workflow node whose target workflow is declared `interactive: true`. A fan-out creates N child runs but the engine reserves a single approval-gate slot, so a child that might pause for human input cannot be governed safely. The check happens before any child is created and fails the parent node with an actionable message.

Source

Thrown at packages/workflows/src/dag-executor.ts:8491

        {
          parentRunId: parentRun.id,
          nodeId: node.id,
          childWorkflow: node.workflow,
          reason: resolved.unresolved,
        },
        'workflow.fan_out_preflight_unresolved'
      );
      await notify(`❌ **Fan-out blocked** (node \`${node.id}\`): ${msg}`);
      return failResult(msg);
    }
    if (resolved.definition.interactive === true) {
      const msg =
        `fan_out node '${node.id}': target workflow '${node.workflow}' is interactive-class ` +
        "('interactive: true') and may pause for human input — a fan-out has a single " +
        'approval-gate slot for N children, so this is refused before any child is created. ' +
        `Remove the pause capability from '${node.workflow}', or invoke it as a single ` +
        "(non-fan-out) 'workflow:' node instead.";
      getLog().warn(
        { parentRunId: parentRun.id, nodeId: node.id, childWorkflow: node.workflow },
        'workflow.fan_out_interactive_target'
      );
      await notify(`❌ **Fan-out blocked** (node \`${node.id}\`): ${msg}`);
      return failResult(msg);
    }
    if (
      node.isolation !== 'worktree' &&
      plannedConcurrency > 1 &&
      resolved.definition.mutates_checkout !== false
    ) {
      const msg = fanOutSharedCheckoutMessage(node, plannedConcurrency);
      getLog().warn(
        {
          parentRunId: parentRun.id,
          nodeId: node.id,
          childWorkflow: node.workflow,
          plannedConcurrency,

View on GitHub (pinned to 0773b97458)

Solutions

  1. Remove `interactive: true` (and its pause/approval paths) from the target workflow if parallel children are intended
  2. Invoke the interactive workflow as a single non-fan-out `workflow:` node so it can use the one approval-gate slot
  3. Create a non-interactive variant of the workflow for fan-out use

Example fix

# before
nodes:
  - id: reviews
    workflow: human-review   # has 'interactive: true'
    fan_out:
      over: items
# after
nodes:
  - id: reviews
    workflow: auto-review    # no interactive flag
    fan_out:
      over: items
Defensive patterns

Strategy: validation

Validate before calling

// Before running, check the fan-out target is not interactive
const def = await workflows.resolve(node.workflow);
if (def.frontmatter.interactive === true) {
  throw new Error(`${node.workflow} is interactive; cannot be used as a fan_out target`);
}

Type guard

function isFanOutSafe(def: { frontmatter: { interactive?: boolean } }): boolean {
  return def.frontmatter.interactive !== true;
}

Prevention

When it happens

Trigger: A `workflow:` node with a `fan_out` block (over items) whose `node.workflow` targets a workflow definition with `interactive: true` in its frontmatter, executed by the DAG executor.

Common situations: Authoring a parallel batch (e.g. fan out per-repo or per-issue tasks) that reuses a workflow originally written as a human-gated review workflow; copying an interactive workflow as a fan-out target without checking its flags.

Related errors


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