n8n-io/n8n · error · Error
Tool name is required
Error message
Tool name is required
What it means
Tool.build() validates that the tool has a non-empty name. The Tool constructor takes a name string, but an empty string passes the constructor signature while failing this runtime check. Every BuiltTool needs a name so the agent loop, tool-call routing, and message serialization can identify it.
Source
Thrown at packages/@n8n/agents/src/sdk/tool.ts:358
* Set provider-specific options forwarded to the AI SDK's `tool()` call.
* Keyed by provider name (e.g. `anthropic`, `openai`).
*
* Example: `.providerOptions({ anthropic: { eagerInputStreaming: true } })`
*/
providerOptions(options: Record<string, JSONObject>): this {
this.providerOptionsValue = { ...this.providerOptionsValue, ...options };
return this;
}
/**
* Validate configuration and produce a `BuiltTool`.
*
* @throws if name, description, input schema, or handler is missing.
* @throws if suspend is declared without resume or vice versa.
*/
build(): BuiltTool {
if (!this.name) {
throw new Error('Tool name is required');
}
if (!this.desc) {
throw new Error(`Tool "${this.name}" requires a description`);
}
if (!this.inputSchema) {
throw new Error(`Tool "${this.name}" requires an input schema`);
}
if (!this.handlerFn) {
throw new Error(`Tool "${this.name}" requires a handler`);
}
const hasSuspend = this.suspendSchemaValue !== undefined;
const hasResume = this.resumeSchemaValue !== undefined;
if (hasSuspend && !hasResume) {
throw new Error(`Tool "${this.name}" has .suspend() but missing .resume()`);
}
if (hasResume && !hasSuspend) {View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass a non-empty, unique name to the Tool constructor: new Tool('search_docs').
- When building tools dynamically, validate the name source before construction and throw a clearer upstream error.
- Use sanitizeToolName-style naming if generating from external input to guarantee a non-empty result.
Example fix
// before
const tool = new Tool('').description('...').handler(...);
agent.tool(tool); // throws during agent's lazy build
// after
const tool = new Tool('search_docs').description('...').handler(...); Defensive patterns
Strategy: validation
Validate before calling
function buildTool(name: string) {
if (typeof name !== 'string' || name.trim().length === 0) {
throw new Error('Tool name must be a non-empty string');
}
return new Tool(name);
} Type guard
function isValidToolName(name: unknown): name is string {
return typeof name === 'string' && name.trim().length > 0;
} Prevention
- Validate dynamic tool names at the source (config load, DB row) before constructing Tool.
- Use a factory that enforces non-empty names so the error never reaches the SDK.
- Treat an empty name as a data-quality bug upstream, not a runtime surprise.
When it happens
Trigger: Constructing new Tool('') (or new Tool(someVariable) where the variable resolves to '') and then either calling .build() directly or — per package convention — passing the builder to agent.tool(...)/agent.tools([...]) which builds internally.
Common situations: Dynamic tool construction from a config file or loop where a name field is missing or whitespace; refactoring and accidentally clearing a name; tests that instantiate Tool with a placeholder empty name.
Related errors
- Tool "${this.name}" requires a description
- Tool "${this.name}" requires an input schema
- Tool "${this.name}" requires a handler
- Tool "${this.name}" has .suspend() but missing .resume()
- Tool "${this.name}" has .resume() but missing .suspend()
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/acad6b0118ad49e5.
Report an issue: GitHub.