n8n-io/n8n · error · Error
${toolName} requires resumeSubAgent and cancelSubAgent to be
Error message
${toolName} requires resumeSubAgent and cancelSubAgent to be configured together What it means
Thrown during createDelegateSubAgentTool when exactly one of resumeSubAgent and cancelSubAgent is provided. The library requires these two callbacks to be configured as a pair because resumption and cancellation are the two lifecycle exits for a suspended child agent — providing one without the other leaves the delegation in a half-configured state that would fail at runtime.
Source
Thrown at packages/@n8n/agents/src/runtime/tools/delegate-sub-agent-tool.ts:459
* agent.tool(createDelegateSubAgentTool({
* runSubAgent: (request) => runner.run(request),
* availableSubAgents,
* policy: { maxChildren: 10 },
* }));
*/
export function createDelegateSubAgentTool(options: CreateDelegateSubAgentToolOptions = {}) {
// Per-parent child path index for stable task paths (/root/name_0, /root/name_1, ...).
const childPathIndexes = new Map<string, number>();
const toolName = resolveDelegateSubAgentToolName(options.name);
const resolvedOptions: CreateDelegateSubAgentToolOptions = {
...options,
policy: resolveDelegateSubAgentPolicy(options.policy, toolName),
};
if (
(resolvedOptions.resumeSubAgent === undefined) !==
(resolvedOptions.cancelSubAgent === undefined)
) {
throw new Error(
`${toolName} requires resumeSubAgent and cancelSubAgent to be configured together`,
);
}
const inlineProviderToolInstruction = resolvedOptions.resolveInlineSubAgentProviderTools
? "Provider-defined tools are loaded for the inline child's selected model provider."
: 'Inline children do not inherit provider-defined tools.';
const toolBuilder = new Tool(toolName)
.description(resolveDelegateSubAgentDescription(resolvedOptions))
.systemInstruction(
resolveDelegateSubAgentSystemInstruction(
resolvedOptions,
toolName,
inlineProviderToolInstruction,
),
)
.input(delegateSubAgentInputSchema)
.output(delegateSubAgentOutputSchema);View on GitHub (pinned to 5ac6606e81)
Solutions
- Provide both resumeSubAgent and cancelSubAgent callbacks together.
- If you do not need suspend/resume support, omit both callbacks entirely.
- If you only need resume, implement a no-op cancelSubAgent that calls the host's cancellation API.
Example fix
// before
const tool = createDelegateSubAgentTool({
resumeSubAgent: (req, helpers) => host.resume(req),
});
// after
const tool = createDelegateSubAgentTool({
resumeSubAgent: (req, helpers) => host.resume(req),
cancelSubAgent: (req, ctx) => host.cancel(req),
}); Defensive patterns
Strategy: validation
Validate before calling
function validateDelegateCallbacks(opts: CreateDelegateSubAgentToolOptions): void {
const hasResume = opts.resumeSubAgent !== undefined;
const hasCancel = opts.cancelSubAgent !== undefined;
if (hasResume !== hasCancel) {
throw new Error('resumeSubAgent and cancelSubAgent must both be provided or both omitted');
}
}
validateDelegateCallbacks(options); Prevention
- Always provide resumeSubAgent and cancelSubAgent as a pair, or omit both.
- Create a factory helper that takes both callbacks or neither to enforce pairing at the type level.
- Document in your team's code review checklist that these two options are coupled.
When it happens
Trigger: Calling createDelegateSubAgentTool({ resumeSubAgent: fn }) without cancelSubAgent, or vice versa. The XOR check (one is undefined, the other is not) is what trips the error.
Common situations: Intending to support suspend/resume of delegated children but forgetting the cancellation handler. Copying a partial configuration from example code that only showed resume. Upgrading from a version where these were independent options to one where they must be paired.
Related errors
- Invalid delegate sub-agent tool name "${name}": must start w
- Model ID is required
- ${toolName} was registered without a runSubAgent callback, a
- ${toolName} host runner does not support inline delegation w
- toolCallConcurrency must be a positive integer or Infinity
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d824faad96b846f2.
Report an issue: GitHub.