{"record":{"id":"acad6b0118ad49e5","repo":"n8n-io/n8n","slug":"tool-name-is-required","errorCode":null,"errorMessage":"Tool name is required","messagePattern":"Tool name is required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/agents/src/sdk/tool.ts","lineNumber":358,"sourceCode":"\t * Set provider-specific options forwarded to the AI SDK's `tool()` call.\n\t * Keyed by provider name (e.g. `anthropic`, `openai`).\n\t *\n\t * Example: `.providerOptions({ anthropic: { eagerInputStreaming: true } })`\n\t */\n\tproviderOptions(options: Record<string, JSONObject>): this {\n\t\tthis.providerOptionsValue = { ...this.providerOptionsValue, ...options };\n\t\treturn this;\n\t}\n\n\t/**\n\t * Validate configuration and produce a `BuiltTool`.\n\t *\n\t * @throws if name, description, input schema, or handler is missing.\n\t * @throws if suspend is declared without resume or vice versa.\n\t */\n\tbuild(): BuiltTool {\n\t\tif (!this.name) {\n\t\t\tthrow new Error('Tool name is required');\n\t\t}\n\t\tif (!this.desc) {\n\t\t\tthrow new Error(`Tool \"${this.name}\" requires a description`);\n\t\t}\n\t\tif (!this.inputSchema) {\n\t\t\tthrow new Error(`Tool \"${this.name}\" requires an input schema`);\n\t\t}\n\t\tif (!this.handlerFn) {\n\t\t\tthrow new Error(`Tool \"${this.name}\" requires a handler`);\n\t\t}\n\n\t\tconst hasSuspend = this.suspendSchemaValue !== undefined;\n\t\tconst hasResume = this.resumeSchemaValue !== undefined;\n\n\t\tif (hasSuspend && !hasResume) {\n\t\t\tthrow new Error(`Tool \"${this.name}\" has .suspend() but missing .resume()`);\n\t\t}\n\t\tif (hasResume && !hasSuspend) {","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/agents/src/sdk/tool.ts#L340-L376","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst tool = new Tool('').description('...').handler(...);\nagent.tool(tool); // throws during agent's lazy build\n\n// after\nconst tool = new Tool('search_docs').description('...').handler(...);","handlingStrategy":"validation","validationCode":"function buildTool(name: string) {\n  if (typeof name !== 'string' || name.trim().length === 0) {\n    throw new Error('Tool name must be a non-empty string');\n  }\n  return new Tool(name);\n}","typeGuard":"function isValidToolName(name: unknown): name is string {\n  return typeof name === 'string' && name.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["tool","builder","validation","configuration"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}