yikart/AiToEarn · error · AppException
ResponseCode.AccountCreateFailed
ResponseCode.AccountCreateFailed
Error message
AccountCreateFailed
What it means
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.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/auth/auth.service.ts:745
nickname: input.displayName,
avatar: input.avatarUrl,
status: AccountStatus.NORMAL,
groupId: input.groupId,
fansCount: input.fansCount,
followingCount: input.followingCount,
}
let account = await this.accountRepo.getByIdentity(identity)
let created = false
if (!account) {
account = await this.accountRepo.createByIdentity(identity, accountData)
created = true
}
if (!created && account && (account.userId === input.userId || !account.userId || input.allowReassign)) {
account = await this.accountRepo.updateByIdentity(identity, accountData) ?? account
}
if (!account) {
throw new AppException(ResponseCode.AccountCreateFailed)
}
if (account.userId !== input.userId) {
this.logger.warn(
{ input, existingAccount: account },
'Channel account already connected to another user',
)
throw new AppException(ResponseCode.ChannelAccountAlreadyConnectedToAnotherUser)
}
return account
}
private async saveSelectableCredential(
accountId: string,
platform: AccountType,
credential: PlatformAccountCredentialSnapshot,
): Promise<void> {
await this.credentialService.saveCredential(accountId, platform, {View on GitHub (pinned to d3aa8bea5b)
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.
Example fix
// before
let account = await this.accountRepo.getByIdentity(identity)
if (!account) account = await this.accountRepo.createByIdentity(identity, accountData)
// after
let account = await this.accountRepo.getByIdentity(identity)
?? await this.accountRepo.createByIdentity(identity, accountData)
if (!account) throw new AppException(ResponseCode.AccountCreateFailed, { identity }) Defensive patterns
Strategy: retry
Validate before calling
const existing = await accountRepo.getByIdentity(identity)
if (!existing) {
const created = await accountRepo.createByIdentity(identity, accountData)
if (!created) throw new AppException(ResponseCode.AccountCreateFailed, { identity })
} Type guard
function isStoredAccount(a: unknown): a is { id: string, userId: string } {
return !!a && typeof (a as any).id === 'string'
} Try / catch
try {
return await handleAuthCallback(input)
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.AccountCreateFailed) {
await sleep(50)
return handleAuthCallback(input) // one retry absorbs the create/update race
}
throw e
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- RelayAccountException
- ResponseCode.ChannelAccountNotAuthorized
- ChannelAccountAlreadyConnectedToAnotherUser
- ChannelAccessTokenFailed
- PlatformNotSupported
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/e037ea7dae3b7062.
Report an issue: GitHub.