yikart/AiToEarn · error · NotFoundException

钱包账户不存在

Error message

钱包账户不存在

What it means

HTTP 404 NotFoundException '钱包账户不存在' thrown when the accountId in the withdraw-cash body does not resolve to a wallet account via financeService.getUserWalletAccountById (task.controller.ts:149). All prior checks (ownership, APPROVED status) passed; only the wallet lookup failed.

Source

Thrown at project/aitoearn-electron/server/src/modules/task/task.controller.ts:149

  // 任务提现(创建提现数据)
  @ApiOperation({ summary: '用户任务提现' })
  @ApiResult({ type: Boolean })
  @Post('withdraw/:id')
  async withdrawCashUserTask(
    @GetToken() token: TokenInfo,
    @Param('id') id: string,
    @Body() data: { accountId: string },
  ) {
    const userTask = await this.userTaskService.getUserTaskInfoById(id);
    if (!userTask || userTask.userId.toString() !== token.id)
      throw new NotFoundException('任务不存在');
    if (userTask.status !== UserTaskStatus.APPROVED)
      throw new NotFoundException('任务状态不正确');
    const account = await this.financeService.getUserWalletAccountById(
      data.accountId,
    );
    if (!account) throw new NotFoundException('钱包账户不存在');

    return await this.financeService.createUserWalletRecord(token.id, account, {
      dataId: userTask.id,
      type: UserWalletRecordType.WITHDRAW,
      balance: userTask.reward, // 将 number 转换为 Decimal128
      des: '任务提现',
      status: UserWalletRecordStatus.WAIT,
    });
  }

  @ApiOperation({ summary: '统计合计进行中的任务的金额总数' })
  @Get('reward/amount')
  @ApiResult({ type: Number })
  async getTotalAmountOfDoingTasks(@GetToken() token: TokenInfo) {
    return await this.taskService.getTotalAmountOfDoingTasks(token.id);
  }

  @ApiOperation({ summary: '获取任务的最优素材' })

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Fetch the user's wallet account list and use a current account id
  2. Ensure accountId is non-empty and correctly bound to the authenticated user
  3. Recreate the wallet account if it was deleted, then retry
  4. Validate accountId client-side before submitting the request

Example fix

// before
await api.withdrawCash(userTask.id, { accountId: cachedAccountId })
// after
const account = await api.getWalletAccounts().then(a => a[0])
await api.withdrawCash(userTask.id, { accountId: account.id })
Defensive patterns

Strategy: validation

Validate before calling

const accounts = await api.getWalletAccounts(token.id)
const account = accounts.find(a => a.id === accountId)
if (!account) throw new Error('Wallet account does not exist for this user')

Type guard

function isValidAccountId(id: unknown): id is string {
  return typeof id === 'string' && /^[a-f\d]{24}$/i.test(id)
}

Try / catch

try {
  await api.withdrawCash(userTaskId, { accountId })
} catch (e) {
  if (e?.status === 404 && e?.message === '钱包账户不存在') {
    // re-fetch wallet accounts and let the user pick a valid one
  } else throw e
}

Prevention

When it happens

Trigger: POST withdraw-cash with data.accountId that has no matching user wallet account: deleted account, account of another user, or a fabricated/truncated id.

Common situations: Client caches wallet account ids after the account was deleted; UI sends an empty string or undefined accountId; multi-account users switch accounts but keep a stale accountId.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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