n8n-io/n8n · error · Error
No cancellation handler is available for "${request.subAgent
Error message
No cancellation handler is available for "${request.subAgentId}". What it means
Thrown from the inline sub-agent wiring inside Agent when the delegate-subagent tool's cancelSubAgent handler receives a cancel request it cannot route. Routing tries the inline sub-agent first (INLINE_SUB_AGENT_ID), then delegates to the host-supplied hostCancelRunner; if neither applies, there is no way to cancel that sub-agent id. The error identifies the unroutable subAgentId verbatim.
Source
Thrown at packages/@n8n/agents/src/sdk/agent.ts:1201
}
if (hostResumeRunner !== undefined) {
return await hostResumeRunner(request, helpersFromHandler);
}
return configuredSubAgentNotFound(request);
},
cancelSubAgent: async (
request: DelegateSubAgentCancelRequest,
helpersFromHandler: DelegateSubAgentRunnerHelpers,
) => {
if (request.subAgentId === INLINE_SUB_AGENT_ID) {
await options.runState.cancel(request.childRunId);
return;
}
if (hostCancelRunner !== undefined) {
await hostCancelRunner(request, helpersFromHandler);
return;
}
throw new Error(
`No cancellation handler is available for "${request.subAgentId}".`,
);
},
}
: {}),
});
if (tool.approval?.required === true) {
return wrapToolForApproval(completedTool, { requireApproval: true });
}
return completedTool;
});
}
private createInlineSubAgentRunner(options: {
deferredTools: BuiltTool[];
modelConfig: ModelConfig;
runState: RunStateManager;View on GitHub (pinned to 5ac6606e81)
Solutions
- Supply a cancelSubAgent handler in the delegate sub-agent options alongside resumeSubAgent so host-managed sub-agents can be cancelled.
- Ensure every subAgentId the runtime can emit is either 'inline' or covered by your host runner.
- If you do not need suspend/resume, do not set resumeSubAgent so childCanSuspend stays false and the cancel handler is never registered.
Example fix
// before
createDelegateSubAgentTool({
runSubAgent: hostRun,
resumeSubAgent: hostResume,
// cancelSubAgent missing
});
// after
createDelegateSubAgentTool({
runSubAgent: hostRun,
resumeSubAgent: hostResume,
cancelSubAgent: async (req, helpers) => { await hostCancel(req, helpers); },
}); Defensive patterns
Strategy: validation
Validate before calling
import { INLINE_SUB_AGENT_ID } from '@n8n/agents';
function assertCancelRoutable(subAgentId: string, hostCancelRunner?: Function) {
if (subAgentId === INLINE_SUB_AGENT_ID) return;
if (typeof hostCancelRunner !== 'function') {
throw new Error(`No host cancelSubAgent for non-inline subAgentId "${subAgentId}"`);
}
} Type guard
function isInlineSubAgentId(id: string): boolean {
return id === 'inline';
} Try / catch
try {
await delegate.cancel(request);
} catch (e) {
if (e instanceof Error && e.message.startsWith('No cancellation handler')) {
// log and degrade: mark the run as un-cancellable, surface to user
} else throw e;
} Prevention
- Always supply cancelSubAgent whenever you supply resumeSubAgent in delegate sub-agent options.
- Treat any non-inline subAgentId as requiring a host runner — validate before wiring.
When it happens
Trigger: A host constructs a delegate sub-agent tool via createDelegateSubAgentTool (or supplies delegateOptions) WITHOUT setting cancelSubAgent, then the runtime issues a DelegateSubAgentCancelRequest whose subAgentId is something other than 'inline'. Because the cancel handler is only registered when childCanSuspend is true, this surfaces during a suspend/resume lifecycle of a host-managed sub-agent.
Common situations: Custom host integrations that wire resumeSubAgent but forget cancelSubAgent; upgrading @n8n/agents and relying on prior behavior where cancellation was a no-op; passing a non-inline subAgentId from a checkpoint-resume path that the host runner does not recognize.
Related errors
- ${toolName} policy.maxChildren must be a finite positive int
- ${toolName} policy.maxChildren must be at least 1
- Delegated child input is missing or invalid
- ${toolName} was registered without a runSubAgent callback, a
- No monitors available
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/35a46f28ecc6ea15.
Report an issue: GitHub.