{"record":{"id":"91d37c2a560644a0","repo":"hcengineering/platform","slug":"badrequest-91d37c","errorCode":"BadRequest","errorMessage":"BadRequest","messagePattern":"BadRequest","errorType":"error_code","errorClass":"PlatformError","httpStatus":400,"severity":"error","filePath":"server/account/src/utils.ts","lineNumber":735,"sourceCode":"  }\n\n  return { account, socialId }\n}\n\nexport async function signUpByGrant (\n  ctx: MeasureContext,\n  db: AccountDB,\n  branding: Branding | null,\n  accountUuid: AccountUuid,\n  grant: PermissionsGrant,\n  info?: LoginInfoRequestData\n): Promise<{ account: AccountUuid, socialId: PersonId }> {\n  const firstName = grant.firstName ?? info?.firstName\n  const lastName = grant.lastName ?? info?.lastName\n\n  if (firstName == null || firstName === '') {\n    ctx.error('First name is required for grant sign up', { grant, info })\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  const existingAccount = await db.account.findOne({ uuid: accountUuid })\n\n  if (existingAccount != null) {\n    ctx.error('An account with the provided uuid already exists', { accountUuid })\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountAlreadyExists, {}))\n  }\n\n  const existingPerson = await db.person.findOne({ uuid: accountUuid })\n\n  if (existingPerson == null) {\n    await db.person.insertOne({ uuid: accountUuid, firstName, lastName: lastName ?? '' })\n  }\n\n  // If there's no account there should be no Huly social id associated with the person if it existed\n  // also, there should be no confirmed social ids associated\n  // so we can safely proceed to account creation","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/utils.ts#L717-L753","documentation":"This BadRequest error is thrown during grant-based sign-up when neither the grant nor the identity info supplies a first name. The operation requires firstName to create the person record, so it fails fast before any DB writes.","triggerScenarios":"Calling the grant sign-up function (server/account/src/utils.ts:735) where grant.firstName and info?.firstName are both null/undefined/'' for the accountUuid.","commonSituations":"OAuth providers that omit given_name in their profile payload; incomplete social profiles (no name shared); grant created programmatically with only email.","solutions":["Ensure the sign-up grant or identity info includes a non-empty firstName","Fall back to a default name (e.g. derive from email or ask the user) when the provider omits it","Validate the profile payload before calling the sign-up function"],"exampleFix":"// before\nawait doGrantSignup(ctx, db, grant, info, accountUuid)\n// after\nconst firstName = grant.firstName ?? info?.firstName ?? email.split('@')[0]\nawait doGrantSignup(ctx, db, { ...grant, firstName }, info, accountUuid)","handlingStrategy":"validation","validationCode":"const firstName = grant.firstName ?? info?.firstName\nif (firstName == null || firstName === '') throw new Error('First name is required for grant sign up')","typeGuard":"function hasFirstName(g: { firstName?: string | null }, i?: { firstName?: string | null } | null): g is { firstName: string } { return (g.firstName ?? i?.firstName ?? '') !== '' }","tryCatchPattern":"try { await doGrantSignup(ctx, db, grant, info, accountUuid) } catch (err) { if (isStatus(err, platform.status.BadRequest)) { /* prompt user for a name */ } else throw err }","preventionTips":["Normalize OAuth profile payloads to always supply a fallback name","Collect the name in onboarding UI when the provider omits it","Validate grant/info fields before calling signup functions"],"tags":["bad-request","validation","signup"],"backgroundTag":"missing-required-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}