coleam00/Archon · error
Loop-group node '${node.id}' exceeded max iterations (${Stri
Error message
Loop-group node '${node.id}' exceeded max iterations (${String(group.max_iterations)}) ${describeUnmetCompletion(group)} What it means
A loop-group node (packages/workflows/src/dag-executor.ts:5404) ran up to group.max_iterations without its until/completion condition being satisfied. The executor logs 'loop_group_node.max_iterations_reached', notifies the conversation, and returns the node failed with the last iteration's output; describeUnmetCompletion appends why the completion signal was unmet.
Source
Thrown at packages/workflows/src/dag-executor.ts:5404
// finalizeLoopFromSignal call above). Only the plain `loop` gate carries it.
});
return {
state: 'completed',
output: lastIterationOutput,
costUsd: loopTotalCostUsd,
...(loopTotalTokens !== undefined ? { tokens: loopTotalTokens } : {}),
loopIterations: i,
};
}
}
// Max iterations exceeded.
const errorMsg = `Loop-group node '${node.id}' exceeded max iterations (${String(group.max_iterations)}) ${describeUnmetCompletion(group)}`;
getLog().warn(
{ nodeId: node.id, maxIterations: group.max_iterations, signal: group.until },
'loop_group_node.max_iterations_reached'
);
await safeSendMessage(platform, conversationId, errorMsg, msgContext);
return {
state: 'failed',
output: lastIterationOutput,
error: errorMsg,
costUsd: loopTotalCostUsd,
...(loopTotalTokens !== undefined ? { tokens: loopTotalTokens } : {}),
loopIterations: group.max_iterations,
};
}
/**
* Clone a body node with `$LOOP_PREV.<id>.output[.field]` refs and `$LOOP_USER_INPUT`
* pre-substituted into every text field a body executor reads prompts from. Used by
* {@link executeLoopGroupNode} so the sealed body sub-DAG's executors stay unaware of the
* enclosing loop iteration (the body's own executors call substituteWorkflowVariables, but
* that uses the run's user_message — not the loop's per-iteration user input — so
* $LOOP_USER_INPUT must be resolved here, at the loop-group level).
*View on GitHub (pinned to 0773b97458)
Solutions
- Read describeUnmetCompletion in the message to see why the condition was never met
- Raise max_iterations on the loop-group node if the work legitimately needs more passes
- Make sure body nodes emit the exact structured field the until condition checks (use structured output)
- Add per-iteration failure handling so a stuck iteration fails fast instead of burning all iterations
Example fix
# workflow yaml
# before
max_iterations: 3
until: "${loop.all_passed}"
# after
max_iterations: 10
until: "${loop.all_passed}" # and ensure body node outputs include all_passed Defensive patterns
Strategy: validation
Validate before calling
// Pre-check that the completion signal's field is actually produced by the body:
const out = await runBodyNodeOnce(group);
if (!(completionField in out)) {
throw new Error(`body output missing completion field '${completionField}' — until will never be satisfied`);
} Type guard
function hasCompletionField(o: unknown, field: string): o is Record<string, unknown> {
return typeof o === 'object' && o !== null && field in o;
} Try / catch
try {
const r = await runLoopGroup(group);
if (r.state === 'failed' && r.error?.includes('exceeded max iterations')) {
console.error(r.error); // includes describeUnmetCompletion — read why the signal was unmet
}
} catch (e) { /* escalate: loops should not be retried blindly */ } Prevention
- Make body nodes emit the exact structured field the until condition checks
- Budget max_iterations generously relative to the work per iteration
- Keep the until expression in sync with the body node's output schema
- Add early-exit criteria so stuck loops fail with a clearer message
When it happens
Trigger: A loop-group whose until condition (e.g. all-done signal, convergence check) never becomes true within max_iterations — completion detection depends on structured output the model/script never emits, or the task genuinely needs more iterations than allowed.
Common situations: Prompt nodes never emitting the expected completion field so the check never passes; max_iterations set too low for the batch size; a condition written against the wrong output field; AI responses drifting from the expected schema.
Related errors
- Loop node '${node.id}' exceeded max iterations (${String(loo
- Loop-group node '${node.id}' failed at iteration ${String(i)
- ❌ **Composed fan-out failed** (node `${node.id}`): ${current
- node_loop_interactive_deprecated
- node_loop_until_deprecated
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/b45042e9905c8398.
Report an issue: GitHub.