{"record":{"id":"ffdc0889bec96cc1","repo":"coleam00/Archon","slug":"workflow-fan-out-interactive-target","errorCode":"workflow.fan_out_interactive_target","errorMessage":"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.","messagePattern":"fan_out node '(.+?)': target 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 '(.+?)', or invoke it as a single \\(non-fan-out\\) 'workflow:' node instead\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflows/src/dag-executor.ts","lineNumber":8491,"sourceCode":"        {\n          parentRunId: parentRun.id,\n          nodeId: node.id,\n          childWorkflow: node.workflow,\n          reason: resolved.unresolved,\n        },\n        'workflow.fan_out_preflight_unresolved'\n      );\n      await notify(`❌ **Fan-out blocked** (node \\`${node.id}\\`): ${msg}`);\n      return failResult(msg);\n    }\n    if (resolved.definition.interactive === true) {\n      const msg =\n        `fan_out node '${node.id}': target workflow '${node.workflow}' is interactive-class ` +\n        \"('interactive: true') and may pause for human input — a fan-out has a single \" +\n        'approval-gate slot for N children, so this is refused before any child is created. ' +\n        `Remove the pause capability from '${node.workflow}', or invoke it as a single ` +\n        \"(non-fan-out) 'workflow:' node instead.\";\n      getLog().warn(\n        { parentRunId: parentRun.id, nodeId: node.id, childWorkflow: node.workflow },\n        'workflow.fan_out_interactive_target'\n      );\n      await notify(`❌ **Fan-out blocked** (node \\`${node.id}\\`): ${msg}`);\n      return failResult(msg);\n    }\n    if (\n      node.isolation !== 'worktree' &&\n      plannedConcurrency > 1 &&\n      resolved.definition.mutates_checkout !== false\n    ) {\n      const msg = fanOutSharedCheckoutMessage(node, plannedConcurrency);\n      getLog().warn(\n        {\n          parentRunId: parentRun.id,\n          nodeId: node.id,\n          childWorkflow: node.workflow,\n          plannedConcurrency,","sourceCodeStart":8473,"sourceCodeEnd":8509,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/dag-executor.ts#L8473-L8509","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove `interactive: true` (and its pause/approval paths) from the target workflow if parallel children are intended","Invoke the interactive workflow as a single non-fan-out `workflow:` node so it can use the one approval-gate slot","Create a non-interactive variant of the workflow for fan-out use"],"exampleFix":"# before\nnodes:\n  - id: reviews\n    workflow: human-review   # has 'interactive: true'\n    fan_out:\n      over: items\n# after\nnodes:\n  - id: reviews\n    workflow: auto-review    # no interactive flag\n    fan_out:\n      over: items","handlingStrategy":"validation","validationCode":"// Before running, check the fan-out target is not interactive\nconst def = await workflows.resolve(node.workflow);\nif (def.frontmatter.interactive === true) {\n  throw new Error(`${node.workflow} is interactive; cannot be used as a fan_out target`);\n}","typeGuard":"function isFanOutSafe(def: { frontmatter: { interactive?: boolean } }): boolean {\n  return def.frontmatter.interactive !== true;\n}","tryCatchPattern":null,"preventionTips":["Keep interactive (human-gated) workflows separate from parallel fan-out targets","Lint workflow YAMLs: forbid fan_out nodes targeting `interactive: true` workflows","Document interactivity in workflow names or frontmatter reviews"],"tags":["workflow","fan-out","interactive"],"backgroundTag":"fan-out-interactive-target-refused","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}