n8n-io/n8n · error
Sub-agent tool requires confirmation but no HITL handler is
Error message
Sub-agent tool requires confirmation but no HITL handler is available
What it means
Thrown by consumeStreamWithHitl (consume-with-hitl.ts:81-83) when options.waitForConfirmation is not provided. Because the function's contract is to suspend on tool-call-suspended chunks and resume after confirmation, a missing handler means suspension cannot be satisfied — the guard fails fast before any streaming begins rather than deadlocking mid-stream.
Source
Thrown at packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts:82
: result.status === 'errored'
? 'failed while streaming'
: `ended with unexpected status "${result.status}"`;
throw new Error(`${agentLabel} ${reason}`);
}
/**
* Consume a sub-agent stream with HITL suspend/resume support.
* Detects `tool-call-suspended` chunks, waits for user confirmation,
* and resumes the stream. Used by delegate, builder, and other agent tools.
*
* Returns `{ text }` — a promise for the agent's full text output.
* When HITL occurred, this returns the resumed stream's text (not the original).
*/
export async function consumeStreamWithHitl(
options: ConsumeWithHitlOptions,
): Promise<ConsumeWithHitlResult> {
if (!options.waitForConfirmation) {
throw new Error('Sub-agent tool requires confirmation but no HITL handler is available');
}
const stream = normalizeStreamSource(options.stream);
const result = await executeResumableStream({
agent: options.agent,
stream,
context: {
threadId: options.threadId,
runId: options.runId,
agentId: options.agentId,
eventBus: options.eventBus,
signal: options.abortSignal,
logger: options.logger,
outputRedaction: options.outputRedaction,
},
control: {
mode: 'auto',
waitForConfirmation: options.waitForConfirmation,View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass a waitForConfirmation callback in ConsumeWithHitlOptions when calling consumeStreamWithHitl.
- If the call site never needs HITL, use the non-HITL consume path instead.
- In tests, provide a mock waitForConfirmation even if it is not exercised.
- Audit the tool wiring to confirm the handler is threaded from the orchestrator context.
Example fix
// before: consumeStreamWithHitl({ agent, stream, runId, agentId, eventBus, logger, threadId, abortSignal })
// after: consumeStreamWithHitl({ agent, stream, runId, agentId, eventBus, logger, threadId, abortSignal, waitForConfirmation }) Defensive patterns
Strategy: type-guard
Validate before calling
function hasHitlHandler(opts: { waitForConfirmation?: unknown }): boolean {
return typeof opts.waitForConfirmation === 'function';
}
if (!hasHitlHandler(options)) throw new Error('consumeStreamWithHitl requires waitForConfirmation'); Type guard
function hasWaitForConfirmation(o: unknown): o is { waitForConfirmation: (id: string) => Promise<Record<string, unknown>> } {
return typeof (o as { waitForConfirmation?: unknown })?.waitForConfirmation === 'function';
} Try / catch
try { return await consumeStreamWithHitl(options); }
catch (e) {
if (e instanceof Error && e.message === 'Sub-agent tool requires confirmation but no HITL handler is available') {
// this is a programming error; fix the call site, do not retry as-is
}
throw e;
} Prevention
- Always thread waitForConfirmation from the orchestrator context into consumeStreamWithHitl.
- If HITL is never needed, use the non-HITL consume path instead.
- Provide a mock handler in tests even when suspension is not exercised.
- Add a type-check on options.waitForConfirmation at the call site.
When it happens
Trigger: consumeStreamWithHitl is invoked without a waitForConfirmation callback. This is a programming error in the caller (the tool wiring), not a runtime data condition. The check runs synchronously on entry.
Common situations: A new sub-agent tool forgot to thread the HITL handler through; a test stub omitted waitForConfirmation; a non-HITL call site mistakenly used consumeStreamWithHitl instead of a plain consume helper.
Related errors
- ${agentLabel} ${reason}
- Human-in-the-Loop nodes cannot be used inside a sub-agent. M
- Model ID is required
- Run ${runId} is not suspended. Cannot resume.
- ${toolName} policy.maxChildren must be a finite positive int
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/a9511529f9ee8c73.
Report an issue: GitHub.