coleam00/Archon · error

Loop node '${node.id}' exceeded max iterations (${String(loo

Error message

Loop node '${node.id}' exceeded max iterations (${String(loop.max_iterations)}) ${describeUnmetCompletion(loop)}

What it means

A loop (while/until) node (packages/workflows/src/dag-executor.ts:7000) exhausted loop.max_iterations without its until condition being satisfied. The executor logs 'loop_node.max_iterations_reached', notifies the conversation, and fails the node via failLoopNode with the last iteration output, iteration count, and maxIterations data.

Source

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

      // in multi-node workflows. Resume correctness relies on the 'paused' DB status, not
      // on the node's output state.
      return {
        state: 'completed',
        output: lastIterationOutput,
        costUsd: loopTotalCostUsd,
        ...(loopTotalTokens !== undefined ? { tokens: loopTotalTokens } : {}),
        loopIterations: i,
      };
    }
  }

  // Max iterations exceeded
  const errorMsg = `Loop node '${node.id}' exceeded max iterations (${String(loop.max_iterations)}) ${describeUnmetCompletion(loop)}`;
  getLog().warn(
    { nodeId: node.id, maxIterations: loop.max_iterations, signal: loop.until },
    'loop_node.max_iterations_reached'
  );
  await safeSendMessage(platform, conversationId, errorMsg, msgContext);
  return failLoopNode(errorMsg, {
    output: lastIterationOutput,
    costUsd: loopTotalCostUsd,
    ...(loopTotalTokens !== undefined ? { tokens: loopTotalTokens } : {}),
    loopIterations: loop.max_iterations,
    data: { maxIterations: loop.max_iterations },
  });
}

/**
 * Pause the run for a human/system gate — the single persist path for all five
 * suspend sites (`loop_group`, `loop`, `approval`, `workflow:` child, and the
 * container write-back gate). By default, tolerates a lost CAS when the run
 * was externally transitioned while the gate was being raised — e.g. a killed
 * CLI's signal cleanup marked the run failed mid-pause (#1123), or an operator
 * cancelled it from another surface. `pauseWorkflowRun`'s UPDATE only matches
 * status='running'; when it misses, re-read the status: any non-running status
 * means the pause lost a legitimate external race — log, skip the

View on GitHub (pinned to 0773b97458)

Solutions

  1. Check the message's describeUnmetCompletion suffix for why the loop signal was never met
  2. Increase max_iterations on the loop node
  3. Verify the body node's structured output actually contains the field referenced by until/while
  4. Add exit criteria or a break condition inside the body so pathological runs terminate early with a clear error

Example fix

# workflow yaml
# before
max_iterations: 5
until: "${steps.review.approved == true}"
# after
max_iterations: 15
until: "${steps.review.approved == true}"  # ensure review node outputs approved as boolean
Defensive patterns

Strategy: validation

Validate before calling

// Prove the loop signal can be satisfied before looping:
const probe = await runBodyOnce(loop);
if (typeof probe[signalField] !== 'boolean') {
  throw new Error(`loop signal field '${signalField}' missing or not boolean in body output`);
}

Type guard

function isLoopResult(r: { state: string; error?: string; data?: { maxIterations?: number } }): r is { state: 'failed'; error: string; data: { maxIterations: number } } {
  return r.state === 'failed' && r.error?.includes('exceeded max iterations') === true;
}

Try / catch

try {
  const r = await runLoopNode(loop);
  if (r.state === 'failed' && r.error?.startsWith('Loop node')) {
    console.error(`${r.error} (ran ${r.data.maxIterations} iterations, output=${JSON.stringify(r.output)})`);
  }
} catch (e) { /* escalate; do not auto-retry an exhausted loop */ }

Prevention

When it happens

Trigger: A loop node whose until/while condition — typically evaluated over a prompt node's structured output — never evaluates true within max_iterations, e.g. the model never emits the sentinel field the signal checks, or the task needs more passes than configured.

Common situations: Agent refine loops where the AI keeps saying 'not done' in the wrong field; max_iterations too low for the convergence needed; a signal expression referencing a renamed output key; retriable external calls failing every pass.

Related errors


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