yikart/AiToEarn · error · AppException

ResponseCode.AccountCreateFailed

ResponseCode.AccountCreateFailed

Error message

AccountCreateFailed

What it means

saveWritableAccount looks up an existing channel account by identity, or creates it via accountRepository.createByIdentity. If the repository returns no account after the create attempt, it throws AppException(ResponseCode.AccountCreateFailed). This indicates the persistence layer failed to create or return the account row.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/accounts/account.service.ts:440

      nickname: relayAccountRef,
      status: AccountStatus.ABNORMAL,
    }
  }

  private async saveWritableAccount(
    identity: AccountIdentity,
    accountData: Partial<Account>,
    userId: string,
  ): Promise<Account> {
    let account = await this.accountRepository.getByIdentity(identity)
    let created = false
    if (!account) {
      account = await this.accountRepository.createByIdentity(identity, accountData)
      created = true
    }

    if (!account) {
      throw new AppException(ResponseCode.AccountCreateFailed)
    }
    if (!created && (account.userId === userId || !account.userId)) {
      account = await this.accountRepository.updateByIdentity(identity, accountData) ?? account
    }
    if (account.userId !== userId) {
      throw new AppException(ResponseCode.ChannelAccountAlreadyConnectedToAnotherUser)
    }

    return account
  }

  private async emitAccountConnected(userId: string, account: Account): Promise<void> {
    await this.eventStream.emit(
      EventStream.Channels,
      EventTopic.ChannelsAccountConnected,
      { userId, accountId: account.id, platform: account.type },
      { source: 'account-service' },
    )

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Check server logs and the repository/DB for a constraint violation or error during createByIdentity.
  2. Retry the account creation — a concurrent-create race may have since committed a row the lookup can find.
  3. Verify identity fields (platform, uid) are correct and not colliding with an existing row in an unexpected state.
  4. Inspect/fix accountRepository.createByIdentity to upsert or surface the underlying DB error instead of returning null.

Example fix

// before
account = await this.accountRepository.createByIdentity(identity, accountData)
// after
account = await this.accountRepository.createByIdentity(identity, accountData) ?? await this.accountRepository.findByIdentity(identity) // tolerate insert-race by re-fetching
Defensive patterns

Strategy: try-catch

Type guard

function isAccountCreateFailed(e: unknown): boolean {
  return e instanceof AppException && e.code === ResponseCode.AccountCreateFailed
}

Try / catch

try {
  account = await accountService.createPluginAccount(userId, identity, data)
} catch (e) {
  if (e instanceof AppException && e.code === ResponseCode.AccountCreateFailed) {
    // inspect DB/logs for constraint violation, then retry once
    account = await accountService.createPluginAccount(userId, identity, data)
  } else throw e
}

Prevention

When it happens

Trigger: accountRepository.createByIdentity returns null/undefined — DB write failure, unique constraint race with a concurrent create, transaction rollback, or the repository returning no row despite no thrown error. Reached from createPluginAccount and createRelayAccountRecord.

Common situations: Duplicate identity inserted concurrently by two plugin callbacks; DB connectivity/constraint issues; identity fields (uid/platform) colliding with an existing row in a way createByIdentity cannot upsert.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/ddc1cd882e52ce7a. Report an issue: GitHub.