{"record":{"id":"d3d655fd584b098d","repo":"mastra-ai/mastra","slug":"plan-capability-not-found","errorCode":null,"errorMessage":"Plan capability not found","messagePattern":"Plan capability not found","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"packages/server/src/server/handlers/plans.ts","lineNumber":44,"sourceCode":"  queryParamSchema: agentPlanQuerySchema,\n  responseSchema: agentPlanResponseSchema,\n  summary: 'Read a submitted agent plan',\n  description:\n    'Returns a markdown plan when the agent exposes the core submit_plan capability and the path is under .mastracode/plans/.',\n  tags: ['Agents', 'Tools'],\n  requiresAuth: true,\n  requiresPermission: MastraFGAPermissions.AGENTS_READ,\n  handler: async ({ agentId, mastra, path, requestContext, status, versionId }) => {\n    try {\n      const versionOptions = versionId ? { versionId } : status ? { status } : undefined;\n      const agent = await getAgentFromSystem({ mastra, agentId, versionOptions, requestContext });\n      const tools = await agent.listTools({ requestContext });\n      const hasSubmitPlan = Object.values(tools).some(\n        tool => typeof tool === 'object' && tool !== null && 'id' in tool && tool.id === submitPlanTool.id,\n      );\n\n      if (!hasSubmitPlan) {\n        throw new HTTPException(404, { message: 'Plan capability not found' });\n      }\n      if (!isPlanPath(path)) {\n        throw new HTTPException(400, { message: 'Invalid plan path' });\n      }\n\n      const workspace = await agent.getWorkspace({ requestContext });\n      const filesystem = await workspace?.resolveFilesystem({ requestContext });\n      if (!filesystem) {\n        throw new HTTPException(404, { message: 'No workspace filesystem configured' });\n      }\n      if (!(await filesystem.exists(path))) {\n        throw new HTTPException(404, { message: `Plan file \"${path}\" not found` });\n      }\n\n      const content = await filesystem.readFile(path, { encoding: 'utf-8' });\n      return {\n        path,\n        content: typeof content === 'string' ? content : content.toString('utf-8'),","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/plans.ts#L26-L62","documentation":"The plans handler inspects the agent's available tools via `agent.listTools()` and requires the submit-plan tool to be present; if the agent lacks that tool capability it throws a 404 'Plan capability not found'. The plan endpoints only work for agents configured with plan-mode tooling.","triggerScenarios":"Calling a plan read/write API for an agent whose toolset does not include the submitPlanTool — agent created without plan-mode tools, tools filtered out by dynamic tool selection/model gating, or wrong agent ID used in the request.","commonSituations":"Pointing plan APIs at a plain agent that never got the plan tool; tool allowlists in model/provider config excluding the plan tool; an older agent definition predating plan-mode support.","solutions":["Add the submit-plan tool to the agent's tool configuration (or enable plan mode on the agent).","Verify you're targeting the correct agent ID that has plan capabilities.","Check any dynamic tool filtering (requestContext-based tools) that may exclude the submit-plan tool at runtime.","Inspect `agent.listTools()` output locally to confirm the plan tool id is present before calling the API."],"exampleFix":"// before\nnew Agent({ name: 'planner', instructions: '...', tools: {} });\n// after\nimport { submitPlanTool } from '@mastra/core/tools';\nnew Agent({ name: 'planner', instructions: '...', tools: { submitPlan: submitPlanTool } });","handlingStrategy":"type-guard","validationCode":"const tools = await agent.listTools({ requestContext });\nconst hasPlanTool = Object.values(tools).some(\n  (t): t is { id: string } => !!t && typeof t === 'object' && 'id' in t && t.id === submitPlanTool.id,\n);\nif (!hasPlanTool) throw new Error('Agent lacks plan capability');","typeGuard":"function isToolWithId(t: unknown): t is { id: string } {\n  return typeof t === 'object' && t !== null && 'id' in t && typeof (t as any).id === 'string';\n}","tryCatchPattern":"try {\n  return await getPlan(agentId, path);\n} catch (e) {\n  if (e.status === 404 && e.message.includes('capability')) {\n    console.error('Enable plan tools on this agent first');\n    return null;\n  }\n  throw e;\n}","preventionTips":["Only expose plan UI/endpoints for agents verified to include the submit-plan tool.","Check dynamic tool filtering doesn't exclude the plan tool at runtime.","Pin agent definitions with plan tools in a shared factory function."],"tags":["http-404","agents","tools","plans"],"backgroundTag":"agent-tool-capability-missing","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}