n8n-io/n8n · error

${agentLabel} ${reason}

Error message

${agentLabel} ${reason}

What it means

Thrown by requireCompletedHitlText (consume-with-hitl.ts:53-68) when a sub-agent stream result is not 'completed'. The status is mapped to a reason: 'cancelled' -> 'was cancelled', 'errored' -> 'failed while streaming', anything else -> a literal 'unexpected status' message. The agentLabel is interpolated to identify which sub-agent failed. This is a post-stream consumer check, not a streaming-layer failure.

Source

Thrown at packages/@n8n/instance-ai/src/stream/consume-with-hitl.ts:67

	/** Accumulated tool call outcomes observed during stream consumption. */
	workSummary: WorkSummary;
}

export async function requireCompletedHitlText(
	result: ConsumeWithHitlResult,
	agentLabel: string,
): Promise<string> {
	if (result.status === 'completed') {
		return await result.text;
	}

	const reason =
		result.status === 'cancelled'
			? 'was cancelled'
			: 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);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Inspect the underlying stream/trace for why the sub-agent reported cancelled or errored.
  2. If cancelled by an abort, retry the parent operation once the abort source is resolved.
  3. Check agent logs and the workSummary for the error chunk that caused 'errored'.
  4. If the status is genuinely unknown, report it as a bug — only 'completed' is considered success.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling requireCompletedHitlText, inspect the result status:
if (result.status !== 'completed') {
  throw new Error(`${agentLabel} ended with status ${result.status}`);
}

Type guard

function isCompletedResult(r: { status: string }): r is { status: 'completed' } {
  return r.status === 'completed';
}

Try / catch

try { return await requireCompletedHitlText(result, agentLabel); }
catch (e) {
  if (e instanceof Error && e.message.includes(agentLabel)) {
    // inspect result.workSummary / trace for the underlying cancel/error cause
  }
  throw e;
}

Prevention

When it happens

Trigger: A sub-agent (delegate/builder/etc.) stream returns with result.status of 'cancelled' or 'errored', or a status the consumer does not recognize. The caller invoked consumeStreamWithHitl and then requireCompletedHitlText on the result.

Common situations: Sub-agent was aborted (cancelled); the underlying LLM call failed (errored); a resume produced an unexpected terminal status; the sub-agent hit its iteration limit and returned a non-completed status.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/1c32971bcb4ea249. Report an issue: GitHub.