{"record":{"id":"667d9749a6abe913","repo":"hcengineering/platform","slug":"platform-status-personnotfound","errorCode":"platform.status.PersonNotFound","errorMessage":"PersonNotFound","messagePattern":"PersonNotFound","errorType":"exception","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":1390,"sourceCode":"  db: AccountDB,\n  branding: Branding | null,\n  token: string\n): Promise<LoginInfo | WorkspaceLoginInfo> {\n  const { account, extra } = decodeTokenVerbose(ctx, token)\n\n  const email = extra?.confirmEmail\n  if (email === undefined) {\n    ctx.error('Email not provided for confirmation', { account, extra })\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))\n  }\n\n  const socialId = await confirmEmail(ctx, db, account, email)\n\n  await confirmHulyIds(ctx, db, account)\n\n  const person = await db.person.findOne({ uuid: account })\n  if (person == null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.PersonNotFound, { person: account }))\n  }\n\n  const result: LoginInfo = {\n    account,\n    name: getPersonName(person),\n    socialId,\n    token: generateToken(account)\n  }\n\n  // If invite info was carried through the confirmation token (signUpJoin flow),\n  // finish the workspace join now that the email is verified.\n  const inviteId = typeof extra?.inviteId === 'string' ? extra.inviteId : ''\n  const workspaceUrl = typeof extra?.workspaceUrl === 'string' ? extra.workspaceUrl : ''\n  if (inviteId !== '' || workspaceUrl !== '') {\n    try {\n      const joinInfo = await getWorkspaceJoinInfo(ctx, db, email, inviteId, workspaceUrl)\n      const joinResult = await doJoinByInvite(\n        ctx,","sourceCodeStart":1372,"sourceCodeEnd":1408,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L1372-L1408","documentation":"After successfully confirming the email (confirmEmail returns a socialId), the handler re-fetches the person record for the account uuid. If it is null the server throws PersonNotFound, meaning the confirmation succeeded but the user profile document is gone or never created.","triggerScenarios":"Confirming email for an account whose person record was deleted (or never created) between sending the confirmation link and clicking it — e.g. admin removed the person, DB migration, or account was purged by a cleanup job.","commonSituations":"Stale confirmation link clicked after the workspace/person was removed; eventual-consistency lag in distributed storage; manual DB cleanup deleted persons but left accounts/social ids.","solutions":["Verify db.person contains a document with uuid equal to the account; recreate it if it was deleted.","Request a new confirmation email and retry with a fresh link if the old person was removed.","Check for cleanup/retention jobs or migrations that delete person records without deleting accounts.","If account is orphaned, remove the account and social ids and have the user sign up again."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await confirmEmailAccount(ctx, token) } catch (err) { if (isStatusError(err, platform.status.PersonNotFound)) show('This account no longer exists; please sign up again'); else throw err }","preventionTips":["Don't delete person records without cleaning up accounts/tokens","Expire confirmation links promptly so stale links fail gracefully","Run consistency checks between accounts and person collections"],"tags":["data-consistency","person-record","database"],"backgroundTag":"record-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}