{"record":{"id":"e9e6a7185525691d","repo":"yikart/AiToEarn","slug":"errhttpback-user-task-err-status","errorCode":"ErrHttpBack.user_task_err_status","errorMessage":"user_task_err_status","messagePattern":"user_task_err_status","errorType":"error_code","errorClass":"AppHttpException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/task/adminUserTask.controller.ts","lineNumber":67,"sourceCode":"    return this.adminUserTaskService.getCompletedTaskCount();\n  }\n\n  @Get('count/approved/user')\n  async getCompletedUserCount() {\n    return this.adminUserTaskService.getCompletedUserCount();\n  }\n\n  // 通过\n  @ApiResult({ type: Boolean })\n  @Put('verify/approved/:id')\n  async verifyUserTaskApproved(\n    @GetToken() verifier: TokenInfo,\n    @Param('id') id: string,\n  ) {\n    const userTask = await this.userTaskService.getUserTaskInfoById(id);\n    if (!userTask) throw new NotFoundException('任务不存在');\n    if (userTask.status !== UserTaskStatus.PENDING)\n      throw new AppHttpException(ErrHttpBack.user_task_err_status);\n\n    return this.adminUserTaskService.verifyUserTaskApproved(userTask, {\n      verifierUserId: verifier.id,\n    });\n  }\n\n  // 拒绝\n  @ApiResult({ type: Boolean })\n  @Put('verify/rejected/:id')\n  async verifyUserTaskRejected(\n    @GetToken() verifier: TokenInfo,\n    @Param('id') id: string,\n    @Body() data: RejectedTaskDto,\n  ) {\n    const userTask = await this.userTaskService.getUserTaskInfoById(id);\n    if (!userTask) throw new NotFoundException('任务不存在');\n    return this.adminUserTaskService.verifyUserTaskRejected(userTask, {\n      verifierUserId: verifier.id,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/task/adminUserTask.controller.ts#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"Concurrent auditors reviewing the same queue entry; stale queue page after someone else approved; retrying a request that actually succeeded the first time.","solutions":["Re-fetch the user task; if it is already APPROVED, treat the operation as done rather than an error.","Refresh the audit queue and retry only if the item still shows PENDING.","Add optimistic locking (check-and-update status atomically in one query) to avoid double processing."],"exampleFix":"// service: atomic status guard\n// before\nreturn this.verifyApproved(userTask, opts);\n// after\nconst res = await this.userTaskModel.findOneAndUpdate(\n  { _id: userTask.id, status: UserTaskStatus.PENDING },\n  { $set: { status: UserTaskStatus.APPROVED, ...opts } },\n);","handlingStrategy":"retry","validationCode":"const ut = await api.getUserTask(id);\nif (ut.status !== 'PENDING') {\n  console.warn(`User task ${id} already ${ut.status}; skipping approve`);\n  return;\n}","typeGuard":"function isPending(t: { status: UserTaskStatus }): boolean {\n  return t.status === UserTaskStatus.PENDING;\n}","tryCatchPattern":"try {\n  await api.put(`/verify/approved/${id}`);\n} catch (e) {\n  const code = e.response?.data?.code;\n  if (code === 'user_task_err_status') {\n    const cur = await api.getUserTask(id);\n    console.warn(`Status changed to ${cur.status}; treating as processed`);\n    return;\n  }\n  throw e;\n}","preventionTips":["Guard status transitions atomically server-side (findOneAndUpdate with status filter).","Disable approve/reject buttons once an item leaves PENDING in the UI.","Make approve/reject idempotent: same result if already in target state."],"tags":["state-machine","task-audit","concurrency","rest"],"backgroundTag":"invalid-state-transition","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}