n8n-io/n8n · error · Error
Deferred tool name collision — the following tool names reso
Error message
Deferred tool name collision — the following tool names resolve to duplicates or reserved tools: ${deferredCollisions.join(', ')} What it means
Thrown by Agent.build() when a deferred tool name collides with an existing static tool name, another deferred tool name, or a reserved tool name (SEARCH_TOOLS_TOOL_NAME, LOAD_TOOL_TOOL_NAME, or any RUNTIME_SKILL_TOOL_NAMES). Deferred tools are loaded on demand, so name conflicts are checked against the full namespace to prevent ambiguity at call time.
Source
Thrown at packages/@n8n/agents/src/sdk/agent.ts:1025
const reservedDeferredToolNames = new Set([
SEARCH_TOOLS_TOOL_NAME,
LOAD_TOOL_TOOL_NAME,
...RUNTIME_SKILL_TOOL_NAMES,
]);
const deferredNames = new Set<string>();
const deferredCollisions: string[] = [];
for (const tool of finalDeferredTools) {
if (
staticNames.has(tool.name) ||
reservedDeferredToolNames.has(tool.name) ||
deferredNames.has(tool.name)
) {
deferredCollisions.push(tool.name);
}
deferredNames.add(tool.name);
}
if (deferredCollisions.length > 0) {
throw new Error(
`Deferred tool name collision — the following tool names resolve to duplicates or reserved tools: ${deferredCollisions.join(', ')}`,
);
}
const collisions = mcpTools
.filter((t) => staticNames.has(t.name) || deferredNames.has(t.name))
.map((t) => t.name);
if (collisions.length > 0) {
throw new Error(
`MCP tool name collision — the following tool names resolve to duplicates: ${collisions.join(', ')}`,
);
}
let allTools = [...finalStaticTools, ...mcpTools];
// Validate checkpoint again after discovering actual MCP tools
// (catches the case where MCP tools have suspendSchema after listing).
const allNeedCheckpoint =View on GitHub (pinned to 5ac6606e81)
Solutions
- Rename the colliding deferred tool to a unique name not present in static, reserved, or other deferred tools.
- Check the error message which lists the colliding names and resolve each one.
- Avoid using reserved names (check RUNTIME_SKILL_TOOL_NAMES, SEARCH_TOOLS_TOOL_NAME, LOAD_TOOL_TOOL_NAME).
Example fix
// before
agent.tools([{ name: 'fetch', ... }])
.deferredTools([{ name: 'fetch', factory: ... }]); // collision
// after
agent.tools([{ name: 'fetch', ... }])
.deferredTools([{ name: 'lazy_fetch', factory: ... }]); Defensive patterns
Strategy: validation
Validate before calling
const RESERVED = new Set([SEARCH_TOOLS_TOOL_NAME, LOAD_TOOL_TOOL_NAME, ...RUNTIME_SKILL_TOOL_NAMES]);
function findDeferredCollisions(staticTools: { name: string }[], deferredTools: { name: string }[]): string[] {
const staticNames = new Set(staticTools.map((t) => t.name));
const seen = new Set<string>();
const collisions: string[] = [];
for (const t of deferredTools) {
if (staticNames.has(t.name) || RESERVED.has(t.name) || seen.has(t.name)) collisions.push(t.name);
seen.add(t.name);
}
return collisions;
} Prevention
- Check deferred tool names against static tool names, reserved names, and other deferred names before building.
- Avoid using reserved names (search_tools, load_tool, runtime skill names) for deferred tools.
- Namespace deferred tools to avoid overlaps with static tools.
When it happens
Trigger: Registering a deferred tool whose name matches a static tool, another deferred tool, or a reserved runtime name. Deferred tools are added via the deferred tool registration path and checked against staticNames, reservedDeferredToolNames, and deferredNames sets.
Common situations: A deferred tool factory generating a name that overlaps with a static tool added in the same build. Using a reserved name like 'search_tools' for a deferred tool. Combining deferred tools from multiple modules with overlapping names.
Related errors
- Static tool name collision — the following tool names resolv
- MCP tool name collision — the following tool names resolve t
- Deferred tool name "${tool.name}" is reserved
- Tool name "${reservedTool.name}" is reserved for runtime ski
- Tool name "${toolName}" is reserved for runtime skills
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d4afaa4e80f7b959.
Report an issue: GitHub.