hcengineering/platform · error · Error

Workspace or account not found in token

Error message

Workspace or account not found in token

What it means

During client connect setup, the token's payload is decoded and must contain both workspace and account claims. If either is missing, handler throws 'Workspace or account not found in token'. This guards against connecting with a token that is not workspace-scoped.

Source

Thrown at foundations/core/packages/client-resources/src/index.ts:128

                return
              }
              if (tx?._class === core.class.TxWorkspaceEvent) {
                const event = tx as TxWorkspaceEvent
                if (event.event === WorkspaceEvent.MaintenanceNotification) {
                  void setPlatformStatus(
                    new Status(Severity.WARNING, platform.status.MaintenanceWarning, {
                      time: event.params.timeMinutes,
                      message: event.params.message ?? ''
                    })
                  )
                }
              }
            }
            handler(...txes)
          }
          const tokenPayload = decodeTokenPayload(token)
          if (tokenPayload.workspace === undefined || tokenPayload.account === undefined) {
            throw new Error('Workspace or account not found in token')
          }

          const newOpt = { ...opt }
          const connectTimeout = opt?.connectionTimeout ?? getMetadata(clientPlugin.metadata.ConnectionTimeout)
          let connectPromise: Promise<void> | undefined
          if ((connectTimeout ?? 0) > 0) {
            connectPromise = new Promise<void>((resolve, reject) => {
              const connectTO = setTimeout(() => {
                if (!clientConnection.isConnected()) {
                  newOpt.onConnect = undefined
                  void clientConnection?.close()
                  void opt?.onDialTimeout?.()
                  reject(new Error(`Connection timeout, and no connection established to ${endpoint}`))
                }
              }, connectTimeout)
              newOpt.onConnect = async (event, lastTx, data) => {
                try {
                  await opt?.onConnect?.(event, lastTx, data)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Obtain the token via getWorkspaceToken, which returns a workspace-scoped token with both claims.
  2. Decode the token payload locally (decodeTokenPayload) and verify workspace/account before connecting.
  3. Re-login to get a fresh, correctly-scoped token.
  4. Check that the token wasn't truncated or altered (valid JWT: header.payload.signature).
  5. Verify client and server auth library versions agree on payload field names.

Example fix

// before
await connect(myLoginToken, ops)
// after
const payload = decodeTokenPayload(myLoginToken)
if (payload.workspace === undefined || payload.account === undefined) {
  const wsToken = await getWorkspaceToken({ token: myLoginToken, workspace })
  await connect(wsToken.token, ops)
} else {
  await connect(myLoginToken, ops)
}
Defensive patterns

Strategy: validation

Validate before calling

import { decodeTokenPayload } from '@hcengineering/client-resources'
const payload = decodeTokenPayload(token)
if (payload.workspace === undefined || payload.account === undefined) {
  token = (await getWorkspaceToken({ token, workspace })).token
}

Type guard

function isWorkspaceToken(p: Record<string, unknown> | undefined): p is { workspace: string, account: string } {
  return p !== undefined && typeof p.workspace === 'string' && typeof p.account === 'string'
}

Try / catch

try {
  await connect(token, ops)
} catch (err) {
  if (err.message.includes('Workspace or account not found in token')) {
    const ws = await getWorkspaceToken({ token, workspace })
    return connect(ws.token, ops)
  }
  throw err
}

Prevention

When it happens

Trigger: Passing a token issued without workspace/account claims (e.g. a bare login token, a malformed JWT, or a token from a different auth scheme) into the client connect/handler flow.

Common situations: Using an account-level token instead of a workspace token; tokens issued by an older/patched auth service with a different payload shape; manually copy-pasted or truncated JWT; decoding with the wrong secret producing garbage payload.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/48e766041205d797. Report an issue: GitHub.