hcengineering/platform · error
Missing workspace role
Error message
Missing workspace role
What it means
withOwnerAsync rejects with 401 'Missing workspace role' when the resolved loginInfo lacks a 'role' property — the account service returned login info that is not workspace-scoped (e.g. global/system login info instead of a workspace membership record).
Source
Thrown at services/payment/pod-payment/src/middleware.ts:91
const withOwnerAsync = async (req: RequestWithAuth, res: Response, next: NextFunction): Promise<void> => {
if (req.token === undefined || req.token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
if (req.params.workspace != null && req.token.workspace !== req.params.workspace) {
res.status(401).json({ message: 'Workspace mismatch' }).end()
return
}
if (req.token.account !== systemAccountUuid && req.token.extra?.admin !== 'true') {
const accountClient = getAccountClient(req.headers.authorization?.split(' ')[1])
const loginInfo = req.loginInfo ?? (await accountClient.getLoginInfoByToken())
if (loginInfo == null) {
res.status(403).json({ message: 'Missing auth info' }).end()
return
}
if (!('role' in loginInfo)) {
res.status(401).json({ message: 'Missing workspace role' }).end()
return
}
if (loginInfo.role !== AccountRole.Owner) {
res.status(401).json({ message: 'Workspace owners only' }).end()
return
}
}
next()
}
View on GitHub (pinned to 63e28dc964)
Solutions
- Add the user to the target workspace with an assigned role in the account service
- Verify the account service version returns workspace-scoped login info including 'role' (check for API drift)
- Ensure the token/workspace used to fetch login info is the same workspace the route targets
- Check that account service data migrations completed for this workspace
Defensive patterns
Strategy: validation
Validate before calling
// verify workspace membership/role before calling owner-guarded routes
const loginInfo = await accountClient.getLoginInfoByToken()
if (loginInfo == null || !('role' in loginInfo)) {
throw new Error('No workspace role: join the workspace before calling this API')
} Type guard
function hasWorkspaceRole(info: unknown): info is { role: AccountRole } {
return typeof info === 'object' && info != null && 'role' in info
} Try / catch
try {
const res = await callWorkspaceApi()
} catch (err) {
if (err.response?.status === 401 && err.response.data?.message === 'Missing workspace role') {
// direct user to join the workspace / check account service membership data
}
} Prevention
- Ensure users are added to the workspace with a role before granting UI access to workspace routes
- Keep account service client and server versions aligned (role field in login info)
- Validate workspace membership on app login and route accordingly
- After data migrations, verify memberships include role fields
When it happens
Trigger: A non-admin caller whose getLoginInfoByToken() result has no 'role' field, meaning they have no workspace-scoped membership record for the token's workspace, or the account client fetched the wrong kind of login info.
Common situations: User authenticated globally but never added to the workspace; account service version returning a shape without role (API change); requesting login info for the wrong workspace context; data migration leaving workspace memberships incomplete.
Related errors
- Workspace mismatch
- platform.status.Unauthorized
- Unauthorized
- Couldn't find workspace with the provided token
- Social ID is missing
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/ff7b5fb64ec7ac98.
Report an issue: GitHub.