hcengineering/platform · error

Invalid workspace login info by token

Error message

Invalid workspace login info by token

What it means

getWorkspaceIds resolves the caller's workspace by fetching login info from the account service with the provided token (getLoginInfoByToken). If the returned object does not pass the isWorkspaceLoginInfo shape check, the token is invalid/expired or not tied to a workspace login, and this error is thrown.

Source

Thrown at pods/server/src/server_http.ts:110

 * @param port -
 * @param host -
 */
export function startHttpServer (
  ctx: MeasureContext,
  sessions: SessionManager,
  port: number,
  accountsUrl: string,
  externalStorage: StorageAdapter
): () => Promise<void> {
  function getAccountClient (token?: string): AccountClient {
    return getAccountClientRaw(accountsUrl, token)
  }

  async function getWorkspaceIds (token: string): Promise<WorkspaceIds> {
    const wsLoginInfo = await getAccountClient(token).getLoginInfoByToken()

    if (!isWorkspaceLoginInfo(wsLoginInfo)) {
      throw new Error('Invalid workspace login info by token')
    }

    return {
      uuid: wsLoginInfo.workspace,
      dataId: wsLoginInfo.workspaceDataId,
      url: wsLoginInfo.workspaceUrl
    }
  }

  if (LOGGING_ENABLED) {
    ctx.info('starting server on', {
      port,
      accountsUrl,
      parallel: os.availableParallelism()
    })
  }

  const app = express()

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Re-authenticate to obtain a fresh valid token and retry the request.
  2. Verify the token is a workspace login token, not a plain account token.
  3. Check account-service connectivity and that getLoginInfoByToken returns the expected workspace fields (workspace, workspaceDataId, workspaceUrl).
  4. Confirm client and server versions agree on the login-info schema.

Example fix

// before
const wsIds = await getWorkspaceIds(token)
// after
const info = await getAccountClient(token).getLoginInfoByToken()
if (!isWorkspaceLoginInfo(info)) {
  throw new UnauthorizedError('token is not a valid workspace token')
}
const wsIds = await getWorkspaceIds(token)
Defensive patterns

Strategy: type-guard

Validate before calling

const info = await getAccountClient(token).getLoginInfoByToken()
if (!isWorkspaceLoginInfo(info)) {
  // refresh token or redirect to login before calling the server
}

Type guard

function isWorkspaceLoginInfo(v: any): v is WorkspaceLoginInfo {
  return v != null && typeof v.workspace === 'string' &&
    typeof v.workspaceDataId === 'string' && typeof v.workspaceUrl === 'string'
}

Try / catch

try {
  const wsIds = await getWorkspaceIds(token)
} catch (err) {
  if (/Invalid workspace login info/.test(err.message)) {
    await reauthenticate() // refresh token and retry once
    return getWorkspaceIds(await getFreshToken())
  }
  throw err
}

Prevention

When it happens

Trigger: An HTTP request to the server with an invalid, expired, revoked, or account-level (non-workspace) token, or the account service being unreachable/misbehaving so getLoginInfoByToken returns an unexpected payload.

Common situations: Expired session tokens on long-lived clients, using an account token where a workspace token is required, account service version mismatch changing the login-info shape, clock skew invalidating tokens.

Related errors


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