hcengineering/platform · error

Workspace or account not found in token

Error message

Workspace or account not found in token

What it means

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.

Source

Thrown at plugins/client-resources/src/index.ts:127

                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. Regenerate the token with a payload that includes both workspace and account claims
  2. Verify the auth service issuing the token populates workspace and account
  3. Log the decoded token payload (decodeTokenPayload) to confirm which field is missing
  4. Ensure the client is passing the correct, current token to connect

Example fix

// before
const token = oldToken // payload: { account: '...' }
// after
const token = await generateToken({ workspace, account }) // both claims present
Defensive patterns

Strategy: validation

Validate before calling

const payload = decodeTokenPayload(token)
if (payload?.workspace === undefined || payload?.account === undefined) {
  throw new Error('Token missing workspace/account claims; regenerate token')
}

Type guard

function hasTokenClaims(t: unknown): t is { workspace: string, account: string } {
  const p = t as any
  return p != null && p.workspace !== undefined && p.account !== undefined
}

Try / catch

try {
  await connect(token, opt)
} catch (err) {
  if (err.message.includes('Workspace or account not found in token')) {
    token = await fetchFreshToken() // re-authenticate
    return connect(token, opt)
  }
  throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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