{"record":{"id":"b28b52a848af4774","repo":"hcengineering/platform","slug":"socialidnotfound","errorCode":"SocialIdNotFound","errorMessage":"platform.status.SocialIdNotFound","messagePattern":"platform\\.status\\.SocialIdNotFound","errorType":"error_code","errorClass":"PlatformError","httpStatus":null,"severity":"error","filePath":"server/account/src/operations.ts","lineNumber":1593,"sourceCode":"\n  // Guard: reject if the account already has a password. The setup flow\n  // bypasses the old-password requirement in changePassword, so it must only\n  // be accessible to accounts that have no password yet.\n  const existingAccount = await getAccount(db, accountUuid)\n  if (existingAccount?.hash != null && existingAccount?.salt != null) {\n    throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {}))\n  }\n\n  ctx.info('Requesting password setup', { accountUuid })\n\n  const emailSocialId = await db.socialId.findOne({\n    type: SocialIdType.EMAIL,\n    personUuid: accountUuid\n  })\n\n  if (emailSocialId == null) {\n    ctx.error('Email social id not found for account', { accountUuid })\n    throw new PlatformError(\n      new Status(Severity.ERROR, platform.status.SocialIdNotFound, { value: '', type: SocialIdType.EMAIL })\n    )\n  }\n\n  const { mailURL, mailAuth } = getMailUrl()\n  const front = getFrontUrl(branding)\n  const resetToken = generateToken(accountUuid, undefined, { restoreEmail: emailSocialId.value })\n  const link = concatLink(front, `/login/recovery?id=${resetToken}`)\n  const lang = branding?.language\n  const text = await translate(accountPlugin.string.PasswordSetupText, { link }, lang)\n  const html = await translate(accountPlugin.string.PasswordSetupHTML, { link }, lang)\n  const subject = await translate(accountPlugin.string.PasswordSetupSubject, {}, lang)\n\n  const response = await fetch(concatLink(mailURL, '/send'), {\n    method: 'post',\n    headers: {\n      'Content-Type': 'application/json',\n      ...(mailAuth != null ? { Authorization: `Bearer ${mailAuth}` } : {})","sourceCodeStart":1575,"sourceCodeEnd":1611,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/account/src/operations.ts#L1575-L1611","documentation":"Thrown during password setup when the accountUuid has no EMAIL-type social ID attached. The account exists (it passed the hash check) but has no email identity, so no setup email can be sent and the flow cannot continue. Status carries an empty value and SocialIdType.EMAIL.","triggerScenarios":"requestPasswordSetup called for an account created without an email social ID (e.g. GitHub/Google-only account, or socialId row missing).","commonSituations":"OAuth-only signups asked to set a password; database where socialId documents were pruned; account created through a non-email signup path; mismatched SocialIdType.","solutions":["Ensure the account has a verified EMAIL social ID before requesting password setup.","Add the email social ID to the account (re-link email) before the setup flow.","Fall back to the identity-provider login for non-email accounts.","Verify db.socialId.findOne({type: SocialIdType.EMAIL, personUuid}) returns a row in your environment."],"exampleFix":"// before: setup for any account\nawait accountClient.requestPasswordSetup(ctx, branding, accountUuid)\n// after: ensure email identity exists\nconst sid = await db.socialId.findOne({ type: SocialIdType.EMAIL, personUuid: accountUuid })\nif (sid == null) throw new Error('Account has no email social id; use OAuth login')\nawait accountClient.requestPasswordSetup(ctx, branding, accountUuid)","handlingStrategy":"validation","validationCode":"const sid = await db.socialId.findOne({ type: SocialIdType.EMAIL, personUuid: accountUuid })\nif (sid == null) throw new Error('Account has no email social id')","typeGuard":"function isEmailSocialId(s: SocialId | null): s is SocialId & { type: SocialIdType.EMAIL } { return s != null && s.type === SocialIdType.EMAIL }","tryCatchPattern":"try {\n  await accountClient.requestPasswordSetup(ctx, branding, accountUuid)\n} catch (err) {\n  if (err instanceof PlatformError && err.status.code === platform.status.SocialIdNotFound) {\n    // direct user to OAuth login or email-linking flow\n  } else throw err\n}","preventionTips":["Require an email social ID at account creation, even for OAuth signups.","Never prune socialId rows without auditing references.","Gate password setup features behind email-identity presence."],"tags":["account","social-id","email"],"backgroundTag":"social-id-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}