{"record":{"id":"891251cec6667c06","repo":"paperclipai/paperclip","slug":"project-workspace-not-found","errorCode":null,"errorMessage":"Project workspace not found","messagePattern":"Project workspace not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"server/src/routes/projects.ts","lineNumber":449,"sourceCode":"      res.json(workspace);\n    },\n  );\n\n  async function handleProjectWorkspaceRuntimeCommand(req: Request, res: Response) {\n    const id = req.params.id as string;\n    const workspaceId = req.params.workspaceId as string;\n    const action = String(req.params.action ?? \"\").trim().toLowerCase();\n    if (action !== \"start\" && action !== \"stop\" && action !== \"restart\" && action !== \"run\") {\n      res.status(404).json({ error: \"Workspace command action not found\" });\n      return;\n    }\n\n    const project = await getAccessibleResource(req, res, svc.getById(id), \"Project not found\");\n    if (!project) return;\n\n    const workspace = project.workspaces.find((entry) => entry.id === workspaceId) ?? null;\n    if (!workspace) {\n      res.status(404).json({ error: \"Project workspace not found\" });\n      return;\n    }\n    if (!(await assertRuntimeManageAllowed(req, res, project.companyId))) return;\n\n    const isSharedWorkspace = Boolean(workspace.sharedWorkspaceKey);\n    if (\n      req.actor.type === \"agent\"\n      && isSharedWorkspace\n      && SHARED_WORKSPACE_STOP_AND_RESTART_ACTIONS.has(action)\n    ) {\n      throw forbidden(\"Missing permission to manage workspace runtime services\");\n    }\n\n    await assertCanManageProjectWorkspaceRuntimeServices(db, req, {\n      companyId: project.companyId,\n      projectWorkspaceId: workspace.id,\n    });\n","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/projects.ts#L431-L467","documentation":"HTTP 404 from handleProjectWorkspaceRuntimeCommand when the workspaceId in the URL does not match any workspace of the project loaded by svc.getById(id). The project itself was found (otherwise 'Project not found'), but the workspace sub-resource is absent, so the handler stops before the authorization check.","triggerScenarios":"Calling a project workspace runtime command endpoint with a stale/deleted workspaceId, a workspaceId belonging to a different project, or a typo'd ID — project.workspaces.find(entry => entry.id === workspaceId) returns null.","commonSituations":"Workspace was deleted after the client cached its ID; client mixes IDs across projects; concurrent project update removed the workspace; copy-paste of workspaceId from another project.","solutions":["Re-fetch the project (GET /api/projects/:id) and use a workspaceId from its current workspaces list.","Confirm the workspaceId belongs to the same project as the :id path parameter.","Recreate the workspace if it was intentionally deleted, then retry with the new ID.","If the workspace exists but isn't returned, check company scoping/filters on the service's getById (actor may not see it)."],"exampleFix":"// before\nPOST /api/projects/p1/workspaces/w_old/runtime/restart   // 404 Project workspace not found\n// after\nconst project = await fetch('/api/projects/p1').then(r => r.json());\nconst wId = project.workspaces[0].id; // use a live workspace id\nPOST `/api/projects/p1/workspaces/${wId}/runtime/restart`","handlingStrategy":"validation","validationCode":"const project = await getProject(projectId);\nconst workspace = project?.workspaces?.find(w => w.id === workspaceId);\nif (!workspace) throw new Error(`workspace ${workspaceId} not found in project ${projectId}`);","typeGuard":"function workspaceExists(project, workspaceId) {\n  return Boolean(project && Array.isArray(project.workspaces) && project.workspaces.some(w => w && w.id === workspaceId));\n}","tryCatchPattern":"try {\n  return await postRuntimeCommand(projectId, workspaceId, cmd);\n} catch (e) {\n  if (isNotFound(e)) {\n    const fresh = await refreshProject(projectId); // re-list workspaces\n    return postRuntimeCommand(projectId, fresh.workspaces[0].id, cmd);\n  }\n  throw e;\n}","preventionTips":["Always re-fetch the project before issuing workspace-scoped commands.","Never cache workspaceIds across sessions or project deletions.","Verify workspaceId and projectId come from the same parent object.","Handle 404 by refreshing the workspace list instead of retrying blindly."],"tags":["http-404","workspace","not-found","rest"],"backgroundTag":"entity-not-found","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}