{"record":{"id":"d729d05df60ce898","repo":"hcengineering/platform","slug":"account-status-badrequest","errorCode":"account.status.BadRequest","errorMessage":"BadRequest","messagePattern":"BadRequest","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":3039,"sourceCode":"export async function deleteAccount (\n  ctx: MeasureContext,\n  db: AccountDB,\n  branding: Branding | null,\n  token: string,\n  params: { uuid?: AccountUuid }\n): Promise<void> {\n  const { extra } = decodeTokenVerbose(ctx, token)\n\n  const isAdmin = extra?.admin === 'true'\n\n  if (!isAdmin) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))\n  }\n\n  const { uuid } = params\n\n  if (uuid == null || uuid === '') {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  await db.deleteAccount(uuid)\n  await db.accountEvent.insertOne({\n    accountUuid: uuid,\n    eventType: AccountEventType.ACCOUNT_DELETED,\n    time: Date.now()\n  })\n}\n\n// Social ids that resolve to an account on their own, and therefore hand over the ability to\n// authenticate as its owner once they are re-pointed. Password recovery and OTP login look an\n// account up by social id value alone (see requestPasswordReset, loginOtp).\nconst loginCapableSocialTypes = [SocialIdType.EMAIL, SocialIdType.HULY]\n\n/**\n * Merging re-points the secondary person's social ids onto the primary person, so an unrestricted\n * caller could both absorb the identifiers of a person they do not own and inject their own","sourceCodeStart":3021,"sourceCodeEnd":3057,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L3021-L3057","documentation":"Thrown when the account-deletion handler receives a null, undefined, or empty string uuid. The admin check has already passed; this validates that the target account identifier is present before calling db.deleteAccount.","triggerScenarios":"Calling the delete-account operation with params.uuid missing, null, or '' — typically a caller that did not resolve the account uuid before invoking the operation.","commonSituations":"Upstream code passes an unpopulated record field; a lookup of the uuid failed silently and null was forwarded; API clients omit the uuid field in the request payload.","solutions":["Resolve and pass a non-empty account uuid in params","Guard the call site against null/empty uuid before invoking","Log/inspect the upstream source of the uuid to find why it is empty"],"exampleFix":"// before\nawait removeAccount(adminToken, account?.uuid) // may be undefined\n// after\nif (!account?.uuid) throw new Error('account uuid missing')\nawait removeAccount(adminToken, account.uuid)","handlingStrategy":"validation","validationCode":"if (uuid == null || uuid === '') throw new Error('account uuid is required')","typeGuard":"function hasUuid(a: { uuid?: string | null } | null | undefined): a is { uuid: string } {\n  return typeof a?.uuid === 'string' && a.uuid !== ''\n}","tryCatchPattern":"try {\n  await removeAccount(adminToken, uuid)\n} catch (err) {\n  if ((err as PlatformError).props?.code === platform.status.BadRequest) {\n    console.error('missing or empty uuid in request params')\n  } else throw err\n}","preventionTips":["Resolve the uuid from a real account record before deleting","Fail fast on empty ids at API boundaries","Type request params as required (non-optional) strings"],"tags":["bad-request","validation","missing-parameter","account"],"backgroundTag":"missing-required-parameter","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}