mastra-ai/mastra · error · HTTPException
Invalid plan path
Error message
Invalid plan path
What it means
After confirming the agent has the plan tool, the plans handler validates the requested file path with `isPlanPath(path)`; paths that don't match the allowed plan-file convention throw a 400 'Invalid plan path'. This guards reads/writes to only designated plan files within the workspace.
Source
Thrown at packages/server/src/server/handlers/plans.ts:47
description:
'Returns a markdown plan when the agent exposes the core submit_plan capability and the path is under .mastracode/plans/.',
tags: ['Agents', 'Tools'],
requiresAuth: true,
requiresPermission: MastraFGAPermissions.AGENTS_READ,
handler: async ({ agentId, mastra, path, requestContext, status, versionId }) => {
try {
const versionOptions = versionId ? { versionId } : status ? { status } : undefined;
const agent = await getAgentFromSystem({ mastra, agentId, versionOptions, requestContext });
const tools = await agent.listTools({ requestContext });
const hasSubmitPlan = Object.values(tools).some(
tool => typeof tool === 'object' && tool !== null && 'id' in tool && tool.id === submitPlanTool.id,
);
if (!hasSubmitPlan) {
throw new HTTPException(404, { message: 'Plan capability not found' });
}
if (!isPlanPath(path)) {
throw new HTTPException(400, { message: 'Invalid plan path' });
}
const workspace = await agent.getWorkspace({ requestContext });
const filesystem = await workspace?.resolveFilesystem({ requestContext });
if (!filesystem) {
throw new HTTPException(404, { message: 'No workspace filesystem configured' });
}
if (!(await filesystem.exists(path))) {
throw new HTTPException(404, { message: `Plan file "${path}" not found` });
}
const content = await filesystem.readFile(path, { encoding: 'utf-8' });
return {
path,
content: typeof content === 'string' ? content : content.toString('utf-8'),
};
} catch (error) {
return handleError(error, 'Error reading submitted plan');View on GitHub (pinned to 75dd419e61)
Solutions
- Use the exact plan path convention the handler expects (the isPlanPath-accepted pattern, e.g. the designated plan file name).
- Log/inspect the path being sent and compare it against isPlanPath's pattern.
- Normalize path separators to forward slashes and avoid absolute paths.
- If you need arbitrary files, use the workspace file APIs instead of plan endpoints.
Example fix
// before
await getPlan('agent-1', '/tmp/other-plan.md'); // rejected
// after
await getPlan('agent-1', 'plan.md'); // matches isPlanPath convention Defensive patterns
Strategy: validation
Validate before calling
const PLAN_PATH = /^plan\.md$/; // match isPlanPath convention
if (!PLAN_PATH.test(path)) throw new Error(`'${path}' is not a valid plan path`); Type guard
function isPlanFilePath(path: string): path is 'plan.md' {
return path === 'plan.md';
} Try / catch
try {
return await getPlan(agentId, path);
} catch (e) {
if (e.status === 400 && e.message === 'Invalid plan path') {
console.error(`Path '${path}' violates the plan path convention`);
return null;
}
throw e;
} Prevention
- Centralize the plan path constant and reuse it in every caller.
- Use forward slashes and relative paths only.
- Never route arbitrary workspace reads through plan endpoints.
When it happens
Trigger: Calling a plan API with a path outside the accepted plan directory/extension (e.g. 'notes.md' instead of the plan path pattern, absolute paths, path traversal attempts, or missing the required prefix like 'plan.md').
Common situations: Hardcoding a path that doesn't match the plan convention; using backslashes on Windows-style paths; trying to read arbitrary workspace files through the plan endpoint; upstream components writing a different plan filename than the handler expects.
Related errors
- bad request: ${responseText}
- Invalid agent-builder action: ${actionId}. Valid actions are
- Invalid agent-builder action: ${actionId}
- Cannot delete the active version. Activate a different versi
- Agent ID is required
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/2a78fa784bb1dd3c.
Report an issue: GitHub.