hcengineering/platform · error

Couldn't find workspace with the provided token

Error message

Couldn't find workspace with the provided token

What it means

The /signin endpoint looks up workspace login info from the account service using the provided token. If the token is valid but does not resolve to a workspace login (isWorkspaceLoginInfo returns false), the endpoint returns 400 with this fixed error string. It means the token identifies an account/user without a workspace context.

Source

Thrown at services/gmail/pod-gmail/src/main.ts:91

  const endpoints: Endpoint[] = [
    {
      endpoint: '/signin',
      type: 'get',
      handler: async (req, res) => {
        try {
          ctx.info('Signin request received')
          const token = extractToken(req.headers)

          if (token === undefined) {
            res.status(401).send()
            return
          }
          const redirectURL = req.query.redirectURL as string

          const accountClient = getAccountClient(token)
          const wsLoginInfo = await accountClient.getLoginInfoByToken()
          if (!isWorkspaceLoginInfo(wsLoginInfo)) {
            res.status(400).send({ err: "Couldn't find workspace with the provided token" })
            return
          }

          const authProvider = gmailController.getAuthProvider()
          const url = authProvider.getAuthUrl(redirectURL, {
            workspace: wsLoginInfo.workspace,
            userId: wsLoginInfo.account
          })
          res.send(url)
        } catch (err) {
          ctx.error('signin error', { message: (err as any).message })
          res.status(500).send()
        }
      }
    },
    {
      endpoint: '/signin/code',
      type: 'get',

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Obtain a workspace-scoped token from the account service (ensure the user has selected/signed into a workspace).
  2. Verify the workspace still exists and the user is a member of it.
  3. Re-authenticate to get a fresh token if the workspace membership changed.
Defensive patterns

Strategy: validation

Validate before calling

// before calling /signin, ensure the token is workspace-scoped:
const loginInfo = await accountClient.getLoginInfoByToken()
if (!loginInfo || !('workspace' in loginInfo) || !loginInfo.workspace) {
  // token does not map to a workspace; fix authentication context first
}

Type guard

function isWorkspaceLoginInfo(info: any): info is { workspace: string; account: string } {
  return info != null && typeof info === 'object' &&
    typeof info.workspace === 'string' && info.workspace.length > 0 &&
    typeof info.account === 'string'
}

Try / catch

const res = await fetch(url + '/signin', { headers })
if (res.status === 400) {
  const body = await res.json()
  if (body?.err === "Couldn't find workspace with the provided token") {
    // prompt user to sign into a workspace and retry with a workspace-scoped token
  }
}

Prevention

When it happens

Trigger: accountClient.getLoginInfoByToken() returns a login info that fails the isWorkspaceLoginInfo guard — i.e. the token belongs to a user/session not tied to a workspace (e.g. a guest or service account token, or a token whose workspace was deleted).

Common situations: Using a personal/user token instead of a workspace-scoped token; the workspace was removed after the token was issued; calling the integration signin flow from a context with no workspace selected.

Related errors


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