{"record":{"id":"f64293a35e5cfd76","repo":"can1357/oh-my-pi","slug":"rpc-host-tool-name-conflicts-with-an-existing","errorCode":null,"errorMessage":"RPC host tool \"${name}\" conflicts with an existing tool","messagePattern":"RPC host tool \"(.+?)\" conflicts with an existing tool","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/session/session-tools.ts","lineNumber":1830,"sourceCode":"\t\t}\n\t}\n\n\t/** Replaces RPC host-owned tools and refreshes the active set before the next model call. */\n\trefreshRpcHostTools(rpcTools: AgentTool[]): Promise<void> {\n\t\tconst snapshot = [...rpcTools];\n\t\treturn this.runToolRegistryMutation(() => this.#applyRpcHostToolRefresh(snapshot));\n\t}\n\n\tasync #applyRpcHostToolRefresh(rpcTools: AgentTool[]): Promise<void> {\n\t\tconst nextToolNames = rpcTools.map(tool => tool.name);\n\t\tconst uniqueToolNames = new Set(nextToolNames);\n\t\tif (uniqueToolNames.size !== nextToolNames.length) {\n\t\t\tthrow new Error(\"RPC host tool names must be unique\");\n\t\t}\n\n\t\tfor (const name of uniqueToolNames) {\n\t\t\tif (this.#toolRegistry.has(name) && !this.#rpcHostToolNames.has(name)) {\n\t\t\t\tthrow new Error(`RPC host tool \"${name}\" conflicts with an existing tool`);\n\t\t\t}\n\t\t}\n\n\t\tconst previousRpcHostToolNames = new Set(this.#rpcHostToolNames);\n\t\tconst previousActiveToolNames = this.getEnabledToolNames();\n\t\tconst previousRpcHostTools = new Map(\n\t\t\t[...previousRpcHostToolNames].flatMap(name => {\n\t\t\t\tconst tool = this.#toolRegistry.get(name);\n\t\t\t\treturn tool ? [[name, tool] as const] : [];\n\t\t\t}),\n\t\t);\n\t\tfor (const name of previousRpcHostToolNames) {\n\t\t\tthis.#toolRegistry.delete(name);\n\t\t}\n\t\tthis.#rpcHostToolNames.clear();\n\n\t\tconst extensionRunner = this.#host.extensionRunner();\n\t\tfor (const tool of rpcTools) {","sourceCodeStart":1812,"sourceCodeEnd":1848,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/session/session-tools.ts#L1812-L1848","documentation":"When refreshing RPC host tools, SessionTools checks each incoming tool name against the existing tool registry. If a name already exists but was NOT previously owned by the RPC host (i.e. it's a built-in or other-source tool), the refresh throws instead of silently overwriting it. This protects built-in tools from being shadowed by externally supplied RPC tools.","triggerScenarios":"An RPC tool refresh supplies a tool whose name collides with an existing registry tool not registered by the RPC host (session-tools.ts:1828-1832): `#toolRegistry.has(name) && !#rpcHostToolNames.has(name)`.","commonSituations":"RPC host registering a tool named 'bash', 'read', 'edit' or another built-in name; renaming a local tool to collide with an RPC tool; loading tool packs that use generic names.","solutions":["Rename the RPC tool to a non-colliding name (e.g. prefix with your host: 'myhost_run_cmd').","List the existing tool names first (session.getEnabledToolNames / registry) and choose unique names.","If intentional replacement is needed, do it through the sanctioned tool-override mechanism rather than the RPC tool refresh path."],"exampleFix":"// before: collides with built-in\nawait session.setRpcTools([{ name: 'bash', ... }]);\n// after\nawait session.setRpcTools([{ name: 'remote_bash', ... }]);","handlingStrategy":"validation","validationCode":"const existing = new Set(session.getEnabledToolNames());\nconst clashes = tools.filter(t => existing.has(t.name)).map(t => t.name);\nif (clashes.length) throw new Error(`names collide with built-ins: ${clashes}`);","typeGuard":null,"tryCatchPattern":"try {\n  await session.setRpcTools(tools);\n} catch (err) {\n  if (/conflicts with an existing tool/.test(err.message)) {\n    logger.error('rename RPC tools; collision with built-in', { err });\n  } else throw err;\n}","preventionTips":["Prefix RPC tool names with a host-specific namespace (e.g. 'myhost_').","Compare against the current registry (getEnabledToolNames) before registering.","Never name RPC tools after built-ins like bash/read/edit.","Keep a fixed manifest of RPC tool names and lint it against the agent's built-in list."],"tags":["rpc","tools","naming-conflict","registry"],"backgroundTag":"tool-name-conflict","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}