hcengineering/platform · error

Invalid workspace

Error message

Invalid workspace

What it means

The export service's export-to-workspace route validates the caller's workspace against the accounts service. If the decoded token's workspace is not present in the account client's workspace info (winfo === undefined) and the caller is not an admin, the route responds 401 with plain text 'Invalid workspace'. It means the token is valid but names a workspace the accounts service does not recognize or the user is not a member of.

Source

Thrown at services/export/pod-export/src/server.ts:322

      if (_class == null) {
        throw new ApiError(400, 'Missing required parameters')
      }

      const decodedToken = decodeToken(token)
      if (decodedToken.extra?.readonly !== undefined) {
        throw new ApiError(403, 'Forbidden')
      }
      const isAdmin: boolean = decodedToken.extra?.admin === 'true'

      const accountClient = getClient(envConfig.AccountsUrl, token)

      try {
        const info = await accountClient.getLoginWithWorkspaceInfo()
        const winfo = info.workspaces[decodedToken.workspace]
        if (!isAdmin) {
          if (winfo === undefined) {
            res.status(401).end('Invalid workspace')
            return
          } else {
            if (winfo.role !== AccountRole.Owner) {
              res.status(401).end('Not an owner of workspace')
              return
            }
          }
        }
      } catch (err: any) {
        res.status(401).end('Invalid workspace')
        return
      }

      const sysToken = generateToken(systemAccountUuid, decodedToken.workspace, {
        service: 'export'
      })

      const platformClient = await createPlatformClient(sysToken)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Re-acquire a fresh login token for the correct workspace so the accounts service lists the caller as a member.
  2. Verify the export service's AccountsUrl env config points to the same accounts instance that issued the token.
  3. Check the workspace exists and the user's membership/role in that workspace is active.
  4. If the user legitimately needs cross-workspace export, have an admin (extra.admin === 'true') perform it or add membership.

Example fix

// before (stale token for old workspace)
const token = oldWorkspaceToken
// after (fresh token for the target workspace)
const login = await fetch(`${accountsUrl}/api/v1/login`, { method: 'POST', body: JSON.stringify({ email, password, workspace: targetWorkspace }) })
const { token } = await login.json()
Defensive patterns

Strategy: validation

Validate before calling

// pre-check membership via accounts client before exporting
const info = await accountClient.getLoginWithWorkspaceInfo()
if (info.workspaces[targetWorkspace] === undefined) {
  throw new Error(`workspace ${targetWorkspace} not accessible for this token`)
}

Try / catch

const res = await exportApi.exportToWorkspace(token, payload)
if (res.status === 401 && (await res.text()) === 'Invalid workspace') {
  throw new Error('token workspace is unknown to accounts — re-login to the target workspace')
}

Prevention

When it happens

Trigger: POST to the export route with a token whose decodedToken.workspace has no entry in accountClient.getLoginWithWorkspaceInfo().workspaces, for a non-admin token.

Common situations: Exporting into a workspace the user was removed from, using a token generated for a deleted/renamed workspace, or stale tokens after workspace migration between environments (dev/prod account URLs mismatch).

Related errors


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