{"record":{"id":"8ff40bdd5a52cb46","repo":"hcengineering/platform","slug":"accountnotfound","errorCode":"AccountNotFound","errorMessage":"platform.status.AccountNotFound","messagePattern":"platform\\.status\\.AccountNotFound","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":1519,"sourceCode":"\n  const normalizedEmail = cleanEmail(email)\n\n  ctx.info('Requesting password reset', { email, normalizedEmail })\n\n  const emailSocialId = await getEmailSocialId(db, normalizedEmail)\n\n  if (emailSocialId == null) {\n    ctx.error('Email social id not found', { email, normalizedEmail })\n    throw new PlatformError(\n      new Status(Severity.ERROR, platform.status.SocialIdNotFound, { value: email, type: SocialIdType.EMAIL })\n    )\n  }\n\n  const account = await getAccount(db, emailSocialId.personUuid as AccountUuid)\n\n  if (account == null) {\n    ctx.info('Account not found', { email, normalizedEmail })\n    throw new PlatformError(\n      new Status(Severity.ERROR, platform.status.AccountNotFound, { account: emailSocialId.personUuid })\n    )\n  }\n\n  const { mailURL, mailAuth } = getMailUrl()\n  const front = getFrontUrl(branding)\n\n  const token = generateToken(account.uuid, undefined, {\n    restoreEmail: normalizedEmail\n  })\n\n  const link = concatLink(front, `/login/recovery?id=${token}`)\n  const lang = branding?.language\n  const text = await translate(accountPlugin.string.RecoveryText, { link }, lang)\n  const html = await translate(accountPlugin.string.RecoveryHTML, { link }, lang)\n  const subject = await translate(accountPlugin.string.RecoverySubject, {}, lang)\n\n  const response = await fetch(concatLink(mailURL, '/send'), {","sourceCodeStart":1501,"sourceCodeEnd":1537,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L1501-L1537","documentation":"Thrown by the account service when looking up an account by a normalized email during email-based social ID operations (e.g. email join/invite flows). The email social ID resolved to a personUuid, but no account exists for that UUID in the database, indicating dangling or inconsistent social-ID data. The Status carries the missing account UUID.","triggerScenarios":"Calling an account operation (e.g. joinByEmailSocialId) where db social ID lookup for SocialIdType.EMAIL yields a personUuid whose account row was deleted or never created.","commonSituations":"Account deletion left orphaned social ID records; workspace backups/restores referencing accounts from another instance; email reused across regions; race between account creation and email verification.","solutions":["Check the account exists for the personUuid (getAccount) before invoking the email-based operation.","Clean up orphaned socialId documents whose personUuid has no matching account.","If migrating/restoring workspaces, ensure accounts were migrated to the same instance first.","Re-trigger the signup flow so the account is created before joining."],"exampleFix":"// before: assume social id implies account\nconst account = await getAccount(db, emailSocialId.personUuid as AccountUuid)\nawait join(ctx, emailSocialId.personUuid)\n// after: guard first\nconst account = await getAccount(db, emailSocialId.personUuid as AccountUuid)\nif (account == null) {\n  await signupAndCreateAccount(ctx, email)\n}","handlingStrategy":"validation","validationCode":"const account = await getAccount(db, emailSocialId.personUuid as AccountUuid)\nif (account == null) {\n  // recreate account or clean up orphaned socialId before proceeding\n}","typeGuard":"function accountExists(a: Account | null | undefined): a is Account { return a != null }","tryCatchPattern":"try {\n  await joinByEmail(ctx, email)\n} catch (err) {\n  if (err instanceof PlatformError && err.status.code === platform.status.AccountNotFound) {\n    await cleanupOrphanedSocialId(email); await reSignup(email)\n  } else throw err\n}","preventionTips":["Delete socialId records together with the account in the same transaction.","After restores/migrations, run an orphaned-socialId consistency check.","Log and monitor AccountNotFound occurrences to catch data drift early."],"tags":["account","social-id","dangling-reference"],"backgroundTag":"account-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}