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
- 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.
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
- 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.
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.