{"record":{"id":"ec27d47fbe40e0db","repo":"can1357/oh-my-pi","slug":"unknown-tool-from-js-runtime-name","errorCode":null,"errorMessage":"Unknown tool from js runtime: ${name}","messagePattern":"Unknown tool from js runtime: (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/eval/js/tool-bridge.ts","lineNumber":42,"sourceCode":"\t\t\ttext: string;\n\t\t\tdetails?: unknown;\n\t\t\timages?: Array<{ mimeType: string; data: string }>;\n\t\t\thasError?: boolean;\n\t  };\nfunction toolResultHasError(result: AgentToolResult): boolean {\n\tif ((result as { isError?: unknown }).isError === true) {\n\t\treturn true;\n\t}\n\tif (!(result.details && typeof result.details === \"object\")) {\n\t\treturn false;\n\t}\n\treturn (result.details as { isError?: unknown }).isError === true;\n}\n\nfunction getTool(session: ToolSession, name: string): AgentTool {\n\tconst tool = session.getToolForEvalBridge ? session.getToolForEvalBridge(name) : session.getToolByName?.(name);\n\tif (!tool) {\n\t\tthrow new ToolError(`Unknown tool from js runtime: ${name}`);\n\t}\n\treturn tool;\n}\n\nfunction normalizeArgs(args: unknown): unknown {\n\tif (!args || typeof args !== \"object\" || Array.isArray(args)) {\n\t\treturn args;\n\t}\n\tconst record = { ...(args as Record<string, unknown>) };\n\tif (record[INTENT_FIELD] === undefined) {\n\t\trecord[INTENT_FIELD] = \"js prelude\";\n\t}\n\treturn record;\n}\n\nfunction summarizeToolResult(\n\tname: string,\n\targs: unknown,","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/eval/js/tool-bridge.ts#L24-L60","documentation":"The eval tool bridge resolves tool names against the current `ToolSession` (via `getToolForEvalBridge` or `getToolByName`). When no tool with the requested name exists, `getTool` throws this `ToolError`. It surfaces to JS eval code that calls a session tool under a wrong/unknown name.","triggerScenarios":"Calling `tool(\"someName\", ...)` or `callSessionTool` from JS eval code with a name that is not registered on the session (typo, tool disabled by config, or MCP server not connected).","commonSituations":"Typo in the tool name; a tool filtered out by permission/allow-list config; an MCP tool missing because the server failed to start; using a builtin name that only exists in other agent versions.","solutions":["Verify the exact tool name — list available tools from the session before calling","Check agent/MCP config so the tool is actually registered and enabled","Guard eval code: check tool availability (if supported) before invoking, or wrap the call in try-catch for ToolError"],"exampleFix":"// before\nawait tool(\"read_file\", { path: \"x.ts\" });\n// after\nawait tool(\"read\", { filePath: \"x.ts\" }); // correct registered name","handlingStrategy":"try-catch","validationCode":"// discover valid tool names first\nconst names = session.tools?.map(t => t.name) ?? [];\nif (!names.includes(name)) throw new Error(`Tool \"${name}\" not available; have: ${names.join(\", \")}`);","typeGuard":null,"tryCatchPattern":"try {\n  await tool(name, args);\n} catch (err) {\n  if (err instanceof ToolError && /Unknown tool from js runtime/.test(err.message)) {\n    // fall back to listing tools or a default tool\n  }\n}","preventionTips":["List session tools before calling; never hardcode names from memory","Check MCP server connectivity so its tools are registered","Review allow-list/permission config that might filter out tools"],"tags":["tool-bridge","eval","tool-not-found"],"backgroundTag":"unknown-tool-name","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}