{"record":{"id":"61db195daecb990e","repo":"can1357/oh-my-pi","slug":"host-tool-name-must-provide-a-non-empty-descr","errorCode":null,"errorMessage":"Host tool \"${name}\" must provide a non-empty description","messagePattern":"Host tool \"(.+?)\" must provide a non-empty description","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/rpc/rpc-mode.ts","lineNumber":505,"sourceCode":"\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});\n}\n\nfunction parseValueDialogResponse(\n\tresponse: RpcExtensionUIResponse,","sourceCodeStart":487,"sourceCodeEnd":523,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/rpc/rpc-mode.ts#L487-L523","documentation":"normalizeHostToolDefinitions requires every host tool to carry a non-empty description: the value must be a string with content after trimming. Descriptions are sent to the LLM so it can decide when to call the tool; an empty one would degrade tool use, so the registration is rejected with this error naming the offending tool.","triggerScenarios":"Registering a host tool whose description is missing, an empty string, or whitespace-only (e.g. description: \"\" or a template that resolved to empty).","commonSituations":"Tool metadata generated from another source where the description field is optional upstream; hand-written tool configs that skip the description for 'obvious' tools.","solutions":["Provide a concise, meaningful 'description' string for the named tool.","If descriptions come from a data source, add a fallback that substitutes a generated description before registration.","Validate tool metadata (name, description, parameters) at the boundary before calling the RPC host-tool registration."],"exampleFix":"// before\n{ name: \"run_shell\", description: \"\", parameters: { type: \"object\" } }\n// after\n{ name: \"run_shell\", description: \"Execute a shell command in the workspace and return its output\", parameters: { type: \"object\" } }","handlingStrategy":"validation","validationCode":"for (const t of tools) {\n  if (typeof t.description !== \"string\" || !t.description.trim()) throw new Error(`Tool ${t.name} missing description`);\n}","typeGuard":"function hasValidDescription(t: { description: unknown }): t is { description: string } {\n  return typeof t.description === \"string\" && t.description.trim().length > 0;\n}","tryCatchPattern":"try {\n  rpc.registerHostTools(tools);\n} catch (err) {\n  if (err instanceof Error && /non-empty description/.test(err.message)) {\n    logger.warn(\"host tool missing description\", { err });\n  } else throw err;\n}","preventionTips":["Make description a required property in the tool definition type.","Generate or default descriptions when the upstream metadata source omits them.","Never register tools with placeholder empty strings; write one line describing when the model should call the tool."],"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"}