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
- Re-acquire a fresh login token for the correct workspace so the accounts service lists the caller as a member.
- Verify the export service's AccountsUrl env config points to the same accounts instance that issued the token.
- Check the workspace exists and the user's membership/role in that workspace is active.
- 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
- Always request tokens scoped to the exact target workspace
- Re-login after membership changes instead of caching tokens
- Keep dev/prod accounts-service URLs consistent across pods
- Use admin tokens only from trusted automation
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
- Invalid workspace login info by token
- Not an owner of workspace
- Unauthorized
- platform.status.BadRequest
- platform.status.WorkspaceNotFound
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/0407c20c6cb6e18c.
Report an issue: GitHub.