{"record":{"id":"50f8f25a7b3fd7ba","repo":"hcengineering/platform","slug":"internalservererror","errorCode":"InternalServerError","errorMessage":"platform.status.InternalServerError","messagePattern":"platform\\.status\\.InternalServerError","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":1685,"sourceCode":"export async function leaveWorkspace (\n  ctx: MeasureContext,\n  db: AccountDB,\n  branding: Branding | null,\n  token: string,\n  params: { account: AccountUuid }\n): Promise<LoginInfo | null> {\n  const { account: targetAccount } = params\n\n  if (targetAccount == null || targetAccount === '') {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  const { account, workspace, extra } = decodeTokenVerbose(ctx, token)\n  ctx.info('Removing account from workspace', { account, workspace })\n\n  if (account == null || workspace == null) {\n    ctx.error('Account or workspace not provided for leaving', { account, workspace })\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))\n  }\n\n  const initiatorRole = await db.getWorkspaceRole(account, workspace)\n  const targetRole = await db.getWorkspaceRole(targetAccount, workspace)\n\n  if (account !== targetAccount) {\n    if (initiatorRole == null || getRolePower(initiatorRole) < getRolePower(AccountRole.Maintainer)) {\n      ctx.error(\"Need to be at least maintainer to remove someone else's account from workspace\", {\n        account,\n        workspace,\n        initiatorRole\n      })\n      throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))\n    }\n\n    if (targetRole === AccountRole.Owner && initiatorRole === AccountRole.Maintainer) {\n      ctx.warn('Maintainer cannot remove owner from workspace', {\n        account,","sourceCodeStart":1667,"sourceCodeEnd":1703,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L1667-L1703","documentation":"Thrown when the remove-account operation's decoded token lacks the initiator account or workspace fields. The token should carry both the acting account and the workspace; their absence indicates a malformed or wrong-kind token, so the service throws InternalServerError instead of continuing.","triggerScenarios":"Passing a token to removeFromWorkspace whose payload has account == null or workspace == null (e.g. a non-workspace token, or token issued without workspace binding).","commonSituations":"Using a global/login token instead of a workspace-scoped token; corrupted token; version mismatch where the workspace claim was renamed or removed.","solutions":["Obtain a workspace-scoped token for the target workspace before the call.","Decode the token (decodeTokenVerbose equivalent) and verify account and workspace claims are present.","Re-login/re-select the workspace to refresh the token.","Align client and server versions so token claims match."],"exampleFix":"// before: any token\nawait accountClient.removeFromWorkspace(anyToken, { account: target })\n// after: workspace token with required claims\nconst claims = decodeTokenVerbose(ctx, token)\nif (claims.account && claims.workspace) {\n  await accountClient.removeFromWorkspace(token, { account: target })\n}","handlingStrategy":"type-guard","validationCode":"const { account, workspace } = decodeTokenVerbose(ctx, token)\nif (account == null || workspace == null) {\n  throw new Error('Token must be workspace-scoped with account and workspace claims')\n}","typeGuard":"function isWorkspaceToken(t: { account?: string | null; workspace?: string | null }): t is { account: string; workspace: string } {\n  return t.account != null && t.workspace != null\n}","tryCatchPattern":"try {\n  await accountClient.removeFromWorkspace(token, { account: target })\n} catch (err) {\n  if (err instanceof PlatformError && err.status.code === platform.status.InternalServerError) {\n    await reLoginToWorkspace(workspace) // refresh workspace-scoped token\n  } else throw err\n}","preventionTips":["Use only workspace-scoped tokens for workspace operations.","Re-acquire tokens after workspace reselection or relogin.","Decode and assert required claims in a shared client wrapper."],"tags":["token","workspace","internal-server-error"],"backgroundTag":"malformed-auth-token","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}