{"record":{"id":"55043d8283766766","repo":"mastra-ai/mastra","slug":"project-path-is-required","errorCode":null,"errorMessage":"Project path is required","messagePattern":"Project path is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"mastracode/sdk/src/agents/workspace.ts","lineNumber":197,"sourceCode":"  return 'npx --yes';\n}\n\nexport async function getDynamicWorkspace({\n  requestContext,\n  mastra,\n  skillExtension,\n}: {\n  requestContext: RequestContext;\n  mastra?: Mastra;\n  skillExtension?: WorkspaceSkillExtension;\n}) {\n  const ctx = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\n  const state = ctx?.getState();\n\n  const rawProjectPath = state?.projectPath;\n\n  if (!rawProjectPath) {\n    throw new Error('Project path is required');\n  }\n\n  const projectPath = path.resolve(rawProjectPath);\n  const configDir = state?.configDir ?? DEFAULT_CONFIG_DIR;\n  const projectSkillPaths = buildSkillPaths(projectPath, configDir, state?.homeDir, state?.pluginSkillPaths ?? []);\n  const skillPaths = [...(skillExtension?.paths ?? []), ...projectSkillPaths];\n  const extensionId = skillExtension ? `-${skillExtension.id}` : '';\n  const workspaceId = `${WORKSPACE_ID_PREFIX}-${projectPath}${extensionId}`;\n  const sandboxPaths = state?.sandboxAllowedPaths ?? [];\n  const allowedPaths = [\n    ...projectSkillPaths,\n    ...DEFAULT_ALLOWED_PATHS,\n    ...sandboxPaths.map((p: string) => path.resolve(p)),\n  ];\n\n  // All modes share the same workspace tool configuration.  Per-mode tool\n  // visibility is enforced at LLM-call time via `availableTools` /\n  // `activeTools` on the AgentController, not by mutating workspace capabilities.","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/agents/workspace.ts#L179-L215","documentation":"`getDynamicWorkspace` builds the agent's workspace (filesystem, sandbox, skills, tools) from the request context's controller state. It reads `state.projectPath` from the `controller` entry in the `RequestContext`; when the context or state is missing, or `projectPath` is empty/undefined, it throws because no workspace root can be resolved for the project.","triggerScenarios":"Calling `getDynamicWorkspace({ requestContext, ... })` where `requestContext.get('controller')` is undefined (no controller registered in the context), the controller has no state yet, or `state.projectPath` is an empty string. Callers include `workspace`, `buildWorkspaceWithLspSetting`, `getGoalJudgeTools`, and `controller` — any of these code paths hitting an uninitialized request context triggers it.","commonSituations":"Invoking agent code outside the normal TUI/server request lifecycle (scripts, tests, one-off tool runs) without seeding the request context; agent sessions started before project selection; `projectPath` omitted from persisted `MastraCodeState` after an upgrade or state migration; running `getGoalJudgeTools` in a headless evaluation harness.","solutions":["Seed the request context with the controller before calling: `requestContext.set('controller', controller)` where the controller's state includes `projectPath`.","Set `state.projectPath` (absolute path to the project root) on the `AgentControllerRequestContext<MastraCodeState>` state before any workspace/tool resolution runs.","Only call `getDynamicWorkspace` (and dependent helpers) after controller initialization; defer workspace construction until the project path is known.","In tests/scripts, construct a controller with `state = { projectPath: <abs path>, ... }` and put it in the RequestContext rather than passing an empty context.","Validate/normalize projectPath upstream and reject sessions without a project before agent execution starts."],"exampleFix":"// before\nconst ws = await getDynamicWorkspace({ requestContext }); // controller never set -> throws\n// after\nrequestContext.set('controller', controller); // controller.state.projectPath = '/abs/path/to/project'\nconst ws = await getDynamicWorkspace({ requestContext });","handlingStrategy":"validation","validationCode":"const ctx = requestContext.get('controller') as AgentControllerRequestContext<MastraCodeState> | undefined;\nif (!ctx?.getState()?.projectPath) {\n  throw new Error('cannot build workspace: controller state has no projectPath');\n}\nconst ws = await getDynamicWorkspace({ requestContext });","typeGuard":"function hasProjectPath(ctx: unknown): ctx is AgentControllerRequestContext<MastraCodeState> & { getState(): MastraCodeState & { projectPath: string } } {\n  const c = ctx as AgentControllerRequestContext<MastraCodeState> | undefined;\n  return typeof c?.getState?.()?.projectPath === 'string' && c.getState().projectPath.length > 0;\n}","tryCatchPattern":"try {\n  const ws = await getDynamicWorkspace({ requestContext });\n} catch (err) {\n  if (err instanceof Error && err.message === 'Project path is required') {\n    // fall back to a default/no-project workspace or prompt the user to open a project\n  } else {\n    throw err;\n  }\n}","preventionTips":["Always set the 'controller' entry in RequestContext before agent/workspace code runs","Initialize controller state with an absolute projectPath before tool resolution","Gate workspace-dependent features until a project is selected/opened","In headless scripts and tests, construct a controller with projectPath in state","Validate projectPath non-empty when persisting/restoring MastraCodeState across versions"],"tags":["configuration","request-context","workspace"],"backgroundTag":"missing-project-path","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}