{"record":{"id":"e21d814961e4cb65","repo":"neoclide/coc.nvim","slug":"unknown-tool-name","errorCode":null,"errorMessage":"Unknown tool: ${name}","messagePattern":"Unknown tool: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/mcp/tools/index.ts","lineNumber":115,"sourceCode":"  }\n\n  public has(name: string): boolean {\n    return this.isAllowed(name) && this.tools.has(name)\n  }\n\n  public list(): { tools: ToolInfo[] } {\n    let tools: ToolInfo[] = []\n    for (let tool of this.tools.values()) {\n      if (!this.isAllowed(tool.name)) continue\n      tools.push(toToolInfo(tool))\n    }\n    return { tools }\n  }\n\n  public async call(name: string, args: any, context: ToolContext): Promise<McpToolResult> {\n    let tool = this.get(name)\n    if (!tool) {\n      throw new Error(`Unknown tool: ${name}`)\n    }\n    return await Promise.resolve(tool.handler(args, context))\n  }\n\n  public dispose(): void {\n    this.tools.clear()\n    this._onDidChange.dispose()\n  }\n}\n","sourceCodeStart":97,"sourceCodeEnd":125,"githubUrl":"https://github.com/neoclide/coc.nvim/blob/50e974d9692461a69147d5cab146a8d3e439abe4/src/mcp/tools/index.ts#L97-L125","documentation":"`ToolRegistry.call` looks up the tool by name via `get`; when no tool with that name is registered it throws 'Unknown tool' rather than silently returning an empty result. This is the dispatch-time counterpart of registration errors.","triggerScenarios":"Calling a tool via the MCP `tools/call` path with a name that was never registered, was unregistered (its Disposable disposed), or is misspelled/differently-cased.","commonSituations":"Client caches the tool list, server restarted and the tool is no longer registered; client sends a name with different casing; extension providing the tool failed to load; stale tool name after a rename across versions.","solutions":["Refresh the client's tool list (tools/list) after server restart","Check the tool name spelling and exact casing","Verify the extension providing the tool is installed and active","Confirm the tool wasn't unregistered (its Disposable disposed) before the call"],"exampleFix":"// before\nawait registry.call('Workspace_Search', args, ctx) // wrong casing\n// after\nawait registry.call('workspace_search', args, ctx)","handlingStrategy":"try-catch","validationCode":"const names = (await registry.tools()).map(t => t.name)\nif (!names.includes(name)) throw new Error(`'${name}' not offered; available: ${names.join(', ')}`)","typeGuard":null,"tryCatchPattern":"try {\n  const result = await registry.call(name, args, ctx)\n} catch (e) {\n  if (/Unknown tool:/.test(e.message)) {\n    await refreshToolList() // re-fetch tools/list after server restart\n    throw new Error(`Tool '${name}' unavailable — refresh and retry`)\n  }\n  throw e\n}","preventionTips":["Refresh the cached tools/list after any server restart","Match tool names exactly, including casing","Verify the providing extension is active before calling","Track Disposable disposal so unregistered tools are removed from clients too"],"tags":["mcp","unknown-identifier","dispatch"],"backgroundTag":"unknown-tool","analyzedSha":"50e974d9692461a69147d5cab146a8d3e439abe4","analyzedAt":"2026-08-31T11:17:23.966Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}