{"record":{"id":"0407c20c6cb6e18c","repo":"hcengineering/platform","slug":"invalid-workspace-0407c2","errorCode":null,"errorMessage":"Invalid workspace","messagePattern":"Invalid workspace","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"services/export/pod-export/src/server.ts","lineNumber":322,"sourceCode":"\n      if (_class == null) {\n        throw new ApiError(400, 'Missing required parameters')\n      }\n\n      const decodedToken = decodeToken(token)\n      if (decodedToken.extra?.readonly !== undefined) {\n        throw new ApiError(403, 'Forbidden')\n      }\n      const isAdmin: boolean = decodedToken.extra?.admin === 'true'\n\n      const accountClient = getClient(envConfig.AccountsUrl, token)\n\n      try {\n        const info = await accountClient.getLoginWithWorkspaceInfo()\n        const winfo = info.workspaces[decodedToken.workspace]\n        if (!isAdmin) {\n          if (winfo === undefined) {\n            res.status(401).end('Invalid workspace')\n            return\n          } else {\n            if (winfo.role !== AccountRole.Owner) {\n              res.status(401).end('Not an owner of workspace')\n              return\n            }\n          }\n        }\n      } catch (err: any) {\n        res.status(401).end('Invalid workspace')\n        return\n      }\n\n      const sysToken = generateToken(systemAccountUuid, decodedToken.workspace, {\n        service: 'export'\n      })\n\n      const platformClient = await createPlatformClient(sysToken)","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/export/pod-export/src/server.ts#L304-L340","documentation":"The export service's export-to-workspace route validates the caller's workspace against the accounts service. If the decoded token's workspace is not present in the account client's workspace info (winfo === undefined) and the caller is not an admin, the route responds 401 with plain text 'Invalid workspace'. It means the token is valid but names a workspace the accounts service does not recognize or the user is not a member of.","triggerScenarios":"POST to the export route with a token whose decodedToken.workspace has no entry in accountClient.getLoginWithWorkspaceInfo().workspaces, for a non-admin token.","commonSituations":"Exporting into a workspace the user was removed from, using a token generated for a deleted/renamed workspace, or stale tokens after workspace migration between environments (dev/prod account URLs mismatch).","solutions":["Re-acquire a fresh login token for the correct workspace so the accounts service lists the caller as a member.","Verify the export service's AccountsUrl env config points to the same accounts instance that issued the token.","Check the workspace exists and the user's membership/role in that workspace is active.","If the user legitimately needs cross-workspace export, have an admin (extra.admin === 'true') perform it or add membership."],"exampleFix":"// before (stale token for old workspace)\nconst token = oldWorkspaceToken\n// after (fresh token for the target workspace)\nconst login = await fetch(`${accountsUrl}/api/v1/login`, { method: 'POST', body: JSON.stringify({ email, password, workspace: targetWorkspace }) })\nconst { token } = await login.json()","handlingStrategy":"validation","validationCode":"// pre-check membership via accounts client before exporting\nconst info = await accountClient.getLoginWithWorkspaceInfo()\nif (info.workspaces[targetWorkspace] === undefined) {\n  throw new Error(`workspace ${targetWorkspace} not accessible for this token`)\n}","typeGuard":null,"tryCatchPattern":"const res = await exportApi.exportToWorkspace(token, payload)\nif (res.status === 401 && (await res.text()) === 'Invalid workspace') {\n  throw new Error('token workspace is unknown to accounts — re-login to the target workspace')\n}","preventionTips":["Always request tokens scoped to the exact target workspace","Re-login after membership changes instead of caching tokens","Keep dev/prod accounts-service URLs consistent across pods","Use admin tokens only from trusted automation"],"tags":["auth","http","workspace","authorization"],"backgroundTag":"invalid-workspace-authorization","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}