yikart/AiToEarn · error · AppHttpException

ErrHttpBack.user_task_err_status

ErrHttpBack.user_task_err_status

Error message

user_task_err_status

What it means

AppHttpException with code user_task_err_status thrown when approving a user task whose status is not PENDING. Only submissions still awaiting review can be approved; this error signals the state machine transition is invalid.

Source

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

    return this.adminUserTaskService.getCompletedTaskCount();
  }

  @Get('count/approved/user')
  async getCompletedUserCount() {
    return this.adminUserTaskService.getCompletedUserCount();
  }

  // 通过
  @ApiResult({ type: Boolean })
  @Put('verify/approved/:id')
  async verifyUserTaskApproved(
    @GetToken() verifier: TokenInfo,
    @Param('id') id: string,
  ) {
    const userTask = await this.userTaskService.getUserTaskInfoById(id);
    if (!userTask) throw new NotFoundException('任务不存在');
    if (userTask.status !== UserTaskStatus.PENDING)
      throw new AppHttpException(ErrHttpBack.user_task_err_status);

    return this.adminUserTaskService.verifyUserTaskApproved(userTask, {
      verifierUserId: verifier.id,
    });
  }

  // 拒绝
  @ApiResult({ type: Boolean })
  @Put('verify/rejected/:id')
  async verifyUserTaskRejected(
    @GetToken() verifier: TokenInfo,
    @Param('id') id: string,
    @Body() data: RejectedTaskDto,
  ) {
    const userTask = await this.userTaskService.getUserTaskInfoById(id);
    if (!userTask) throw new NotFoundException('任务不存在');
    return this.adminUserTaskService.verifyUserTaskRejected(userTask, {
      verifierUserId: verifier.id,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Re-fetch the user task; if it is already APPROVED, treat the operation as done rather than an error.
  2. Refresh the audit queue and retry only if the item still shows PENDING.
  3. Add optimistic locking (check-and-update status atomically in one query) to avoid double processing.

Example fix

// service: atomic status guard
// before
return this.verifyApproved(userTask, opts);
// after
const res = await this.userTaskModel.findOneAndUpdate(
  { _id: userTask.id, status: UserTaskStatus.PENDING },
  { $set: { status: UserTaskStatus.APPROVED, ...opts } },
);
Defensive patterns

Strategy: retry

Validate before calling

const ut = await api.getUserTask(id);
if (ut.status !== 'PENDING') {
  console.warn(`User task ${id} already ${ut.status}; skipping approve`);
  return;
}

Type guard

function isPending(t: { status: UserTaskStatus }): boolean {
  return t.status === UserTaskStatus.PENDING;
}

Try / catch

try {
  await api.put(`/verify/approved/${id}`);
} catch (e) {
  const code = e.response?.data?.code;
  if (code === 'user_task_err_status') {
    const cur = await api.getUserTask(id);
    console.warn(`Status changed to ${cur.status}; treating as processed`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: PUT verify/approved/:id where userTask.status is already APPROVED, REJECTED, or any non-PENDING value — e.g. double-clicking approve or approving after another admin already processed it.

Common situations: Concurrent auditors reviewing the same queue entry; stale queue page after someone else approved; retrying a request that actually succeeded the first time.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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