{"record":{"id":"e037ea7dae3b7062","repo":"yikart/AiToEarn","slug":"responsecode-accountcreatefailed-e037ea","errorCode":"ResponseCode.AccountCreateFailed","errorMessage":"AccountCreateFailed","messagePattern":"AccountCreateFailed","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/auth/auth.service.ts","lineNumber":745,"sourceCode":"      nickname: input.displayName,\n      avatar: input.avatarUrl,\n      status: AccountStatus.NORMAL,\n      groupId: input.groupId,\n      fansCount: input.fansCount,\n      followingCount: input.followingCount,\n    }\n    let account = await this.accountRepo.getByIdentity(identity)\n    let created = false\n    if (!account) {\n      account = await this.accountRepo.createByIdentity(identity, accountData)\n      created = true\n    }\n    if (!created && account && (account.userId === input.userId || !account.userId || input.allowReassign)) {\n      account = await this.accountRepo.updateByIdentity(identity, accountData) ?? account\n    }\n\n    if (!account) {\n      throw new AppException(ResponseCode.AccountCreateFailed)\n    }\n    if (account.userId !== input.userId) {\n      this.logger.warn(\n        { input, existingAccount: account },\n        'Channel account already connected to another user',\n      )\n      throw new AppException(ResponseCode.ChannelAccountAlreadyConnectedToAnotherUser)\n    }\n\n    return account\n  }\n\n  private async saveSelectableCredential(\n    accountId: string,\n    platform: AccountType,\n    credential: PlatformAccountCredentialSnapshot,\n  ): Promise<void> {\n    await this.credentialService.saveCredential(accountId, platform, {","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/auth/auth.service.ts#L727-L763","documentation":"createOrUpdateAccount throws AccountCreateFailed (AppException, ResponseCode.AccountCreateFailed) when after attempting both createByIdentity and updateByIdentity there is still no account object. This happens if creation failed/returned null (e.g. a repository error or race condition swallowed by the repo returning null) and no pre-existing account matched the identity, so the code cannot proceed to store the credential.","triggerScenarios":"accountRepo.createByIdentity throws or returns null (DB write failure, unique-index race with a concurrent OAuth callback for the same platform+uid), and updateByIdentity also yields nothing because the identity row is absent.","commonSituations":"Duplicate OAuth callbacks racing to create the same platform account (double redirect, user double-clicking authorize); MongoDB transient write errors; repository mocked/misconfigured in tests returning undefined.","solutions":["Retry the authorization callback — transient races usually resolve on a second attempt once the first write lands.","Check server logs / MongoDB health for write errors at createByIdentity time (connection issues, index conflicts).","Make identity creation idempotent/upsert-style so a concurrent duplicate callback cannot leave `account` null.","Verify the identity fields (platform, platformUid, and for YouTube the account handle) are non-empty and consistent between lookup and create."],"exampleFix":"// before\nlet account = await this.accountRepo.getByIdentity(identity)\nif (!account) account = await this.accountRepo.createByIdentity(identity, accountData)\n// after\nlet account = await this.accountRepo.getByIdentity(identity)\n  ?? await this.accountRepo.createByIdentity(identity, accountData)\nif (!account) throw new AppException(ResponseCode.AccountCreateFailed, { identity })","handlingStrategy":"retry","validationCode":"const existing = await accountRepo.getByIdentity(identity)\nif (!existing) {\n  const created = await accountRepo.createByIdentity(identity, accountData)\n  if (!created) throw new AppException(ResponseCode.AccountCreateFailed, { identity })\n}","typeGuard":"function isStoredAccount(a: unknown): a is { id: string, userId: string } {\n  return !!a && typeof (a as any).id === 'string'\n}","tryCatchPattern":"try {\n  return await handleAuthCallback(input)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.AccountCreateFailed) {\n    await sleep(50)\n    return handleAuthCallback(input) // one retry absorbs the create/update race\n  }\n  throw e\n}","preventionTips":["Use upsert semantics on identity to make creation idempotent under duplicate OAuth callbacks.","Guard the OAuth callback against double submission (state parameter, one-time nonce).","Check Mongo replica health if AccountCreateFailed clusters in time.","Log the identity when this throws to spot duplicate-callback races."],"tags":["persistence","race-condition","channels","mongodb"],"backgroundTag":"record-creation-failed","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}