{"record":{"id":"7add6217c772ed7c","repo":"can1357/oh-my-pi","slug":"host-tool-at-index-index-must-provide-a-non-emp","errorCode":null,"errorMessage":"Host tool at index ${index} must provide a non-empty name","messagePattern":"Host tool at index (.+?) must provide a non-empty name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/rpc/rpc-mode.ts","lineNumber":501,"sourceCode":"\t\t\tconst cancelled = !(await session.switchSession(command.sessionPath));\n\t\t\tif (!cancelled) subagentRegistry?.clear();\n\t\t\treturn { type: \"switch_session\", data: { cancelled } };\n\t\t}\n\n\t\tcase \"branch\": {\n\t\t\tconst result = await session.branch(command.entryId);\n\t\t\tif (!result.cancelled) subagentRegistry?.clear();\n\t\t\treturn { type: \"branch\", data: { text: result.selectedText, cancelled: result.cancelled } };\n\t\t}\n\t}\n\tthrow new Error(\"Unsupported RPC session change command\");\n}\n\nfunction normalizeHostToolDefinitions(tools: RpcHostToolDefinition[]): RpcHostToolDefinition[] {\n\treturn tools.map((tool, index) => {\n\t\tconst name = typeof tool.name === \"string\" ? tool.name.trim() : \"\";\n\t\tif (!name) {\n\t\t\tthrow new Error(`Host tool at index ${index} must provide a non-empty name`);\n\t\t}\n\t\tconst description = typeof tool.description === \"string\" ? tool.description.trim() : \"\";\n\t\tif (!description) {\n\t\t\tthrow new Error(`Host tool \"${name}\" must provide a non-empty description`);\n\t\t}\n\t\tif (!tool.parameters || typeof tool.parameters !== \"object\" || Array.isArray(tool.parameters)) {\n\t\t\tthrow new Error(`Host tool \"${name}\" must provide a JSON Schema object`);\n\t\t}\n\t\tconst label = typeof tool.label === \"string\" && tool.label.trim() ? tool.label.trim() : name;\n\t\treturn {\n\t\t\tname,\n\t\t\tlabel,\n\t\t\tdescription,\n\t\t\tparameters: tool.parameters,\n\t\t\thidden: tool.hidden === true,\n\t\t\tloadMode: defaultLoadModeForToolName(name, tool.loadMode),\n\t\t};\n\t});","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/rpc/rpc-mode.ts#L483-L519","documentation":"normalizeHostToolDefinitions validates each host-provided tool before registering it with the agent. The tool's name must be a string that is non-empty after trimming; otherwise this error is thrown with the tool's array index. It ensures every host tool has an identifier usable for dispatch.","triggerScenarios":"Registering host tools via the tools option with an entry whose name is undefined, an empty string, whitespace-only, or a non-string (e.g. a number or null).","commonSituations":"Programmatic tool list generation where one entry's name field is omitted or built from an empty variable; JSON configs where 'name' was misspelled so it defaults to undefined.","solutions":["Set a non-empty 'name' string on the tool entry at the reported index.","If names are generated, validate/trim them before passing the array and drop or repair entries with empty names.","Fix config key casing so the name field is actually read (e.g. 'name' not 'Name')."],"exampleFix":"// before\nconst tools = [{ description: \"Run a shell command\", parameters: { type: \"object\" } }];\n// after\nconst tools = [{ name: \"run_shell\", description: \"Run a shell command\", parameters: { type: \"object\" } }];","handlingStrategy":"validation","validationCode":"tools.forEach((t, i) => {\n  if (typeof t.name !== \"string\" || !t.name.trim()) throw new Error(`Tool at index ${i} missing non-empty name`);\n});","typeGuard":"function hasValidName(t: { name: unknown }): t is { name: string } {\n  return typeof t.name === \"string\" && t.name.trim().length > 0;\n}","tryCatchPattern":"try {\n  rpc.registerHostTools(tools);\n} catch (err) {\n  if (err instanceof Error && /must provide a non-empty name/.test(err.message)) {\n    logger.warn(\"skipping host tool with empty name\", { err });\n  } else throw err;\n}","preventionTips":["Build tool definitions from a typed interface with a required name field so TS catches omissions.","Trim and validate names at the point where tool metadata is generated.","Watch for casing mismatches ('Name' vs 'name') when loading tools from JSON config."],"tags":["validation","rpc","tools","configuration"],"backgroundTag":"tool-definition-validation","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}