{"record":{"id":"1fe13de242448fa5","repo":"hcengineering/platform","slug":"account-status-badrequest-1fe13d","errorCode":"account.status.BadRequest","errorMessage":"BadRequest","messagePattern":"BadRequest","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/serviceOperations.ts","lineNumber":237,"sourceCode":"    }\n  }\n  return ops > 0\n}\n\nexport async function updateWorkspaceRoleBySocialKey (\n  ctx: MeasureContext,\n  db: AccountDB,\n  branding: Branding | null,\n  token: string,\n  params: {\n    socialKey: string\n    targetRole: AccountRole\n  }\n): Promise<void> {\n  const { socialKey, targetRole } = params\n\n  if (socialKey == null || socialKey === '' || targetRole == null || !assignableRoles.includes(targetRole)) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  const { extra } = decodeTokenVerbose(ctx, token)\n  verifyAllowedServices(['workspace', 'tool'], extra)\n\n  const socialId = await getSocialIdByKey(db, socialKey.toLowerCase() as PersonId)\n  if (socialId == null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountNotFound, {}))\n  }\n\n  await updateWorkspaceRole(ctx, db, branding, token, { targetAccount: socialId.personUuid as AccountUuid, targetRole })\n}\n\n/**\n * Retrieves one workspace for which there are things to process.\n *\n * Workspace is provided for 30seconds. This timeout is reset\n * on every progress update.","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/serviceOperations.ts#L219-L255","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure socialKey is a non-empty string (it will be lowercased internally) before calling","Validate targetRole against the assignableRoles list exported by this service before sending","If the role must be assignable but is rejected, check that client and server versions agree on the AccountRole enum"],"exampleFix":"// before\nawait updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole: userProvidedRole })\n// after\nconstAssignableRoles = assignableRoles as readonly AccountRole[]\nif (socialKey !== '' && socialKey != null && assignableRoles.includes(userProvidedRole)) {\n  await updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole: userProvidedRole })\n}","handlingStrategy":"validation","validationCode":"import { assignableRoles } from '@hcengineering/account'\nconst isValidRole = (r: unknown): r is AccountRole =>\n  typeof r === 'string' && assignableRoles.includes(r as AccountRole)\nif (typeof socialKey !== 'string' || socialKey === '' || !isValidRole(targetRole)) {\n  throw new Error('Invalid socialKey or targetRole for updateWorkspaceRoleBySocialKey')\n}","typeGuard":"function isAssignableRole(role: unknown): role is AccountRole {\n  return typeof role === 'string' && assignableRoles.includes(role as AccountRole)\n}","tryCatchPattern":"try {\n  await updateWorkspaceRoleBySocialKey(ctx, db, branding, token, { socialKey, targetRole })\n} catch (err) {\n  if (err instanceof PlatformError && err.status.code === platform.status.BadRequest) {\n    // validate socialKey/targetRole inputs and retry with corrected payload\n  } else throw err\n}","preventionTips":["Validate targetRole against assignableRoles at every call site / API boundary","Never pass user-supplied role strings directly; whitelist-map them first","Ensure socialKey is trimmed, non-empty, and lowercased before sending","Keep AccountRole enums synchronized between client and server versions"],"tags":["validation","bad-request","roles","account"],"backgroundTag":"invalid-request-parameters","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}