hcengineering/platform · error

Not an owner of workspace

Error message

Not an owner of workspace

What it means

The API returns 401 'Not an owner of workspace' when the token is valid and the workspace exists, but the authenticated user's role in that workspace is not AccountRole.Owner and the token does not carry admin='true'. The backup download endpoint is restricted to owners (or admins) even for workspace members.

Source

Thrown at services/backup/backup-api-pod/src/server.ts:194

      isAdmin = decoded.extra?.admin === 'true'
    } catch (err: any) {
      res.status(401).end('Unauthorized')
      return
    }
    let wsInfo: WorkspaceIds | undefined = wsInfoCache.get(workspaceId)
    const accountClient = getClient(config.AccountsUrl, token)

    if (wsInfo === undefined) {
      try {
        const info = await accountClient.getLoginWithWorkspaceInfo()
        const winfo = info.workspaces[workspaceId]
        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
            }
          }
        }
        const wssInfo = await accountClient.getWorkspaceInfo()
        wsInfo = {
          url: wssInfo.url,
          dataId: wssInfo.dataId,
          uuid: workspaceId
        }
        wsInfoCache.set(workspaceId, wsInfo)
      } catch (err: any) {
        res.status(401).end('Invalid workspace')
        return
      }
    }

    const dataId = wsInfo.dataId ?? (wsInfo.uuid as unknown as WorkspaceDataId)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Request the backup using a token from a workspace Owner account
  2. Have an Owner promote your role to Owner in workspace settings
  3. If you operate the service, issue a token with extra.admin='true' for automation
  4. Re-login to refresh membership info if your role was recently changed

Example fix

// before
// token of a Member role user
const token = memberToken
// after
const token = ownerToken // token of an AccountRole.Owner user
Defensive patterns

Strategy: validation

Validate before calling

const winfo = info.workspaces[workspaceUuid]
if (!isAdmin && winfo?.role !== AccountRole.Owner) {
  throw new Error('Backup download requires Owner role')
}

Type guard

function isOwnerOrAdmin(winfo: { role: AccountRole } | undefined, isAdmin: boolean): boolean {
  return isAdmin || winfo?.role === AccountRole.Owner
}

Try / catch

try { ... } catch (e) {
  if (e.message === 'Not an owner of workspace') throw new Error('Request an Owner to run the backup download')
  throw e
}

Prevention

When it happens

Trigger: GET /api/backup/<workspaceUuid>/<file> with a token whose account membership has role Member/Guest rather than Owner, and extra.admin !== 'true'.

Common situations: A regular team member tries to download backup archives, an owner downgraded their own role, or the account service reports a stale role after a recent promotion.

Related errors


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