{"record":{"id":"7c74012e884ea754","repo":"mastra-ai/mastra","slug":"tool-id-is-required","errorCode":null,"errorMessage":"Tool ID is required","messagePattern":"Tool ID is required","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/tools.ts","lineNumber":238,"sourceCode":"  },\n});\n\nexport const EXECUTE_TOOL_ROUTE = createRoute({\n  method: 'POST',\n  path: '/tools/:toolId/execute',\n  responseType: 'json',\n  pathParamSchema: toolIdPathParams,\n  queryParamSchema: optionalRunIdSchema,\n  bodySchema: executeToolContextBodySchema,\n  responseSchema: executeToolResponseSchema,\n  summary: 'Execute tool',\n  description: 'Executes a specific tool with the provided input data',\n  tags: ['Tools'],\n  requiresAuth: true,\n  handler: async ({ mastra, runId, toolId, registeredTools, requestContext, ...bodyParams }) => {\n    try {\n      if (!toolId) {\n        throw new HTTPException(400, { message: 'Tool ID is required' });\n      }\n\n      let tool: any;\n\n      // Try explicit registeredTools first, then fallback to mastra\n      if (registeredTools && Object.keys(registeredTools).length > 0) {\n        tool = Object.values(registeredTools).find((t: any) => t.id === toolId);\n      }\n      if (!tool) {\n        try {\n          tool = mastra.getToolById(toolId);\n        } catch {\n          // tool not found in global registry, continue to agent fallback\n        }\n      }\n\n      // Fallback: search dynamically-resolved agent tools (toolsResolver)\n      if (!tool) {","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/tools.ts#L220-L256","documentation":"A 400 validation error from the tool execution endpoint when the request omits the toolId parameter entirely. The handler requires toolId before attempting any tool resolution.","triggerScenarios":"POST to the tool execution route with no toolId in path/body (or toolId resolving to undefined/null/empty), e.g. calling the execute endpoint directly without identifying which tool to run.","commonSituations":"Building custom client code that forgets to pass the tool ID; generic proxy that strips route params; calling the execute endpoint instead of a tool-specific nested route.","solutions":["Include the toolId in the request path or body when calling the execute endpoint.","Ensure your client serializes route params and doesn't drop them (check URL construction).","Fetch the tool list first and pass a valid toolId."],"exampleFix":"// before\nawait api.post('/api/tools/execute', { data: { city: 'Tokyo' } }); // 400\n// after\nawait api.post(`/api/tools/${toolId}/execute`, { data: { city: 'Tokyo' } });","handlingStrategy":"validation","validationCode":"if (typeof toolId !== 'string' || toolId.trim() === '') {\n  throw new Error('toolId is required to execute a tool');\n}","typeGuard":"function hasToolId(args: { toolId?: string }): args is { toolId: string } {\n  return typeof args.toolId === 'string' && args.toolId.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate required params at the client boundary.","Use typed route helpers that require the tool path segment.","Unit-test request builders for missing params."],"tags":["http-400","validation","tools","api"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}