{"record":{"id":"67472c3a1ded73bd","repo":"can1357/oh-my-pi","slug":"invoketool-no-native-built-in-named-name-to","errorCode":null,"errorMessage":"invokeTool: no native built-in named \"${name}\" to delegate to","messagePattern":"invokeTool: no native built-in named \"(.+?)\" to delegate to","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/extensibility/extensions/runner.ts","lineNumber":584,"sourceCode":"\t */\n\tasync invokeNativeTool<TDetails = unknown>(\n\t\tname: string,\n\t\tparams: Record<string, unknown>,\n\t\toptions?: {\n\t\t\tsignal?: AbortSignal;\n\t\t\tonUpdate?: AgentToolUpdateCallback<TDetails>;\n\t\t\tdepth?: number;\n\t\t\t/**\n\t\t\t * The caller tool's own context. Reused for the native call so metadata the native tool\n\t\t\t * reads — `toolCall` (write/edit LSP batch flushing) and provider metadata /\n\t\t\t * `providerSafetyApproved` (computer) — is preserved. Falls back to a fresh session tool\n\t\t\t * context only when the caller had none.\n\t\t\t */\n\t\t\tcallerContext?: AgentToolContext;\n\t\t},\n\t): Promise<AgentToolResult<TDetails>> {\n\t\tconst resolved = this.#nativeToolResolver?.(name);\n\t\tif (!resolved) throw new Error(`invokeTool: no native built-in named \"${name}\" to delegate to`);\n\t\tconst depth = options?.depth ?? 0;\n\t\tif (depth >= 8) {\n\t\t\tthrow new Error(`invokeTool: delegation depth exceeded 8 (recursive invokeTool for \"${name}\"?)`);\n\t\t}\n\t\tconst toolCallId = `invoke-${name}-${Date.now().toString(36)}-${depth}`;\n\t\treturn (await resolved.tool.execute(\n\t\t\ttoolCallId,\n\t\t\tparams as never,\n\t\t\toptions?.signal,\n\t\t\toptions?.onUpdate as never,\n\t\t\toptions?.callerContext ?? resolved.makeContext(),\n\t\t)) as AgentToolResult<TDetails>;\n\t}\n\n\tconstructor(\n\t\tprivate readonly extensions: Extension[],\n\t\tprivate readonly runtime: ExtensionRuntime,\n\t\t/** Ignored: `cwd` is always read live via the `cwd` getter below, not cached here. */","sourceCodeStart":566,"sourceCodeEnd":602,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/extensibility/extensions/runner.ts#L566-L602","documentation":"ExtensionRunner.invokeTool delegates to a native built-in tool looked up via the #nativeToolResolver callback. When the resolver returns nothing (no resolver installed or no built-in registered under that name), invokeTool throws this Error instead of executing.","triggerScenarios":"An extension calls runner.invokeTool('bash', ...) but the host never wired a nativeToolResolver, or the tool name is misspelled/not a registered built-in at invoke time.","commonSituations":"Extension invokes a tool by a name that was renamed in a newer version; invoking from a host context (test/SDK) where native tools were not attached; typo in the tool name string.","solutions":["Verify the tool name matches a currently registered native built-in (check getAllTools()/registry).","Ensure the runner is constructed with a nativeToolResolver (host wiring) before invokeTool is used.","Guard the call: check resolvability or feature availability first, and surface a clear message for unknown tools."],"exampleFix":"// before\nawait runner.invokeTool('bash_tool', params); // wrong name\n// after\nconst known = runner.getAllTools().some(t => t.name === 'bash');\nif (!known) throw new Error('bash tool unavailable in this host');\nawait runner.invokeTool('bash', params);","handlingStrategy":"validation","validationCode":"const name = 'bash';\nif (!runner.getAllTools().some(t => t.name === name)) {\n  throw new Error(`tool '${name}' not available in this host`);\n}\nawait runner.invokeTool(name, params);","typeGuard":"function canInvoke(runner: ExtensionRunner, name: string): boolean {\n  return typeof runner.#resolveNative === 'function'; // or check a public resolvability API\n}","tryCatchPattern":"try {\n  return await runner.invokeTool(name, params);\n} catch (err) {\n  if (err.message.startsWith('invokeTool: no native built-in')) {\n    throw new Error(`tool '${name}' is not registered in this host; check name and host wiring`);\n  }\n  throw err;\n}","preventionTips":["Keep tool names in a shared constants file; never inline strings.","Confirm the host attaches a nativeToolResolver before extensions use invokeTool.","Check getAllTools() or a registry before invoking dynamically chosen names.","Verify tool names after upgrading the CLI (names can be renamed)."],"tags":["extensions","tool-invocation","delegation"],"backgroundTag":"unknown-tool-name","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}