{"record":{"id":"f318a593665ccdd7","repo":"hcengineering/platform","slug":"workspace-or-account-not-found-in-token-f318a5","errorCode":null,"errorMessage":"Workspace or account not found in token","messagePattern":"Workspace or account not found in token","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/client-resources/src/index.ts","lineNumber":127,"sourceCode":"                return\n              }\n              if (tx?._class === core.class.TxWorkspaceEvent) {\n                const event = tx as TxWorkspaceEvent\n                if (event.event === WorkspaceEvent.MaintenanceNotification) {\n                  void setPlatformStatus(\n                    new Status(Severity.WARNING, platform.status.MaintenanceWarning, {\n                      time: event.params.timeMinutes,\n                      message: event.params.message ?? ''\n                    })\n                  )\n                }\n              }\n            }\n            handler(...txes)\n          }\n          const tokenPayload = decodeTokenPayload(token)\n          if (tokenPayload.workspace === undefined || tokenPayload.account === undefined) {\n            throw new Error('Workspace or account not found in token')\n          }\n\n          const newOpt = { ...opt }\n          const connectTimeout = opt?.connectionTimeout ?? getMetadata(clientPlugin.metadata.ConnectionTimeout)\n          let connectPromise: Promise<void> | undefined\n          if ((connectTimeout ?? 0) > 0) {\n            connectPromise = new Promise<void>((resolve, reject) => {\n              const connectTO = setTimeout(() => {\n                if (!clientConnection.isConnected()) {\n                  newOpt.onConnect = undefined\n                  void clientConnection?.close()\n                  void opt?.onDialTimeout?.()\n                  reject(new Error(`Connection timeout, and no connection established to ${endpoint}`))\n                }\n              }, connectTimeout)\n              newOpt.onConnect = async (event, lastTx, data) => {\n                try {\n                  await opt?.onConnect?.(event, lastTx, data)","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/plugins/client-resources/src/index.ts#L109-L145","documentation":"During the websocket upgrade handler the connection token is decoded and must contain both a workspace and an account identifier. If either is missing the library cannot scope the new client connection and throws immediately, aborting the upgrade. This is a fail-fast validation of the authentication token payload.","triggerScenarios":"Connecting with a token whose decoded payload lacks 'workspace' or 'account' fields; using a malformed, truncated, or wrong-type token; passing a token generated by a different system or older schema.","commonSituations":"Misconfigured authentication service issuing incomplete tokens; stale tokens from before a schema change; environment misconfiguration pointing at the wrong auth server; hand-crafted or copied tokens missing claims.","solutions":["Regenerate the token with a payload that includes both workspace and account claims","Verify the auth service issuing the token populates workspace and account","Log the decoded token payload (decodeTokenPayload) to confirm which field is missing","Ensure the client is passing the correct, current token to connect"],"exampleFix":"// before\nconst token = oldToken // payload: { account: '...' }\n// after\nconst token = await generateToken({ workspace, account }) // both claims present","handlingStrategy":"validation","validationCode":"const payload = decodeTokenPayload(token)\nif (payload?.workspace === undefined || payload?.account === undefined) {\n  throw new Error('Token missing workspace/account claims; regenerate token')\n}","typeGuard":"function hasTokenClaims(t: unknown): t is { workspace: string, account: string } {\n  const p = t as any\n  return p != null && p.workspace !== undefined && p.account !== undefined\n}","tryCatchPattern":"try {\n  await connect(token, opt)\n} catch (err) {\n  if (err.message.includes('Workspace or account not found in token')) {\n    token = await fetchFreshToken() // re-authenticate\n    return connect(token, opt)\n  }\n  throw err\n}","preventionTips":["Validate token payload claims right after receiving it from the auth service","Ensure the token issuer always includes workspace and account","Detect auth-server schema changes in CI by decoding a sample token","Use fresh tokens; avoid hand-copied or outdated ones"],"tags":["auth","token","validation"],"backgroundTag":"invalid-token-claims","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}