hcengineering/platform · error · PlatformError

account.status.BadRequest

account.status.BadRequest

Error message

BadRequest

What it means

updateWorkspaceRoleBySocialKey validates its inputs before doing any work: socialKey must be a non-empty string and targetRole must be one of the assignableRoles. If either fails, a PlatformError with platform.status.BadRequest is thrown. This is a request-validation guard, not a state or permission error — the request payload itself is bad.

Source

Thrown at server/account/src/serviceOperations.ts:237

    }
  }
  return ops > 0
}

export async function updateWorkspaceRoleBySocialKey (
  ctx: MeasureContext,
  db: AccountDB,
  branding: Branding | null,
  token: string,
  params: {
    socialKey: string
    targetRole: AccountRole
  }
): Promise<void> {
  const { socialKey, targetRole } = params

  if (socialKey == null || socialKey === '' || targetRole == null || !assignableRoles.includes(targetRole)) {
    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))
  }

  const { extra } = decodeTokenVerbose(ctx, token)
  verifyAllowedServices(['workspace', 'tool'], extra)

  const socialId = await getSocialIdByKey(db, socialKey.toLowerCase() as PersonId)
  if (socialId == null) {
    throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountNotFound, {}))
  }

  await updateWorkspaceRole(ctx, db, branding, token, { targetAccount: socialId.personUuid as AccountUuid, targetRole })
}

/**
 * Retrieves one workspace for which there are things to process.
 *
 * Workspace is provided for 30seconds. This timeout is reset
 * on every progress update.

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Ensure socialKey is a non-empty string (it will be lowercased internally) before calling
  2. Validate targetRole against the assignableRoles list exported by this service before sending
  3. If the role must be assignable but is rejected, check that client and server versions agree on the AccountRole enum

Example fix

// before
await updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole: userProvidedRole })
// after
constAssignableRoles = assignableRoles as readonly AccountRole[]
if (socialKey !== '' && socialKey != null && assignableRoles.includes(userProvidedRole)) {
  await updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole: userProvidedRole })
}
Defensive patterns

Strategy: validation

Validate before calling

import { assignableRoles } from '@hcengineering/account'
const isValidRole = (r: unknown): r is AccountRole =>
  typeof r === 'string' && assignableRoles.includes(r as AccountRole)
if (typeof socialKey !== 'string' || socialKey === '' || !isValidRole(targetRole)) {
  throw new Error('Invalid socialKey or targetRole for updateWorkspaceRoleBySocialKey')
}

Type guard

function isAssignableRole(role: unknown): role is AccountRole {
  return typeof role === 'string' && assignableRoles.includes(role as AccountRole)
}

Try / catch

try {
  await updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole })
} catch (err) {
  if (err instanceof PlatformError && err.status.code === platform.status.BadRequest) {
    // validate socialKey/targetRole inputs and retry with corrected payload
  } else throw err
}

Prevention

When it happens

Trigger: Calling updateWorkspaceRoleBySocialKey with an empty/missing socialKey, an undefined/null targetRole, or a targetRole not in assignableRoles (e.g. an AccountRole string that is not assignable via this endpoint, like an owner or system role).

Common situations: Client sending role names from an outdated enum; role values sourced from user input without whitelisting; empty socialId keys from incomplete user profiles or unmapped social accounts in service-to-service calls from 'workspace'/'tool' services.

Related errors


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