{"record":{"id":"aa7e9d0d7b528b9c","repo":"yikart/AiToEarn","slug":"errhttpback-user-task-no-had","errorCode":"ErrHttpBack.user_task_no_had","errorMessage":"user_task_no_had","messagePattern":"user_task_no_had","errorType":"error_code","errorClass":"AppHttpException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/task/task.controller.ts","lineNumber":109,"sourceCode":"    const res = await this.userTaskService.userApplyTask(token.id, task, body);\n\n    if (!!body.taskMaterialId)\n      this.taskService.upTaskMaterialUsedCount(body.taskMaterialId);\n\n    return res;\n  }\n\n  @ApiOperation({ summary: '提交任务 id是用户任务ID' })\n  @ApiResult({ type: Boolean })\n  @Post('submit/:id')\n  async submitTask(\n    @GetToken() token: TokenInfo,\n    @Param('id') id: string,\n    @Body() data: SubmitTaskDto,\n  ) {\n    const userTask = await this.userTaskService.getUserTaskInfoById(id);\n    if (!userTask || userTask.userId.toString() !== token.id)\n      throw new AppHttpException(ErrHttpBack.user_task_no_had);\n\n    const res = await this.userTaskService.submitTask(userTask, data);\n\n    if (res.status === UserTaskStatus.PENDING) {\n      this.bullTaskAuditQueue.add(\n        'start',\n        {\n          userTaskId: id,\n        },\n        {\n          attempts: 5, // 这个作业特定的重试次数\n          backoff: {\n            type: 'fixed', // 固定间隔重试\n            delay: 1000 * 30, // 每次重试间隔5秒\n          },\n        },\n      );\n    }","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/task/task.controller.ts#L91-L127","documentation":"AppHttpException with ErrHttpBack.user_task_no_had (errCode 60010, message '用户任务不存在'), a 404-style business error. Thrown by the submitTask controller when the userTask id in the path does not exist OR exists but belongs to a different user than the token. It doubles as an ownership check, so it can also mean 'not yours'.","triggerScenarios":"PUT/POST submit to /task/user/:id/submit (task.controller.ts:109) where getUserTaskInfoById(id) returns null, or userTask.userId !== token.id — e.g. submitting a wrong id, a task of another account, or with an expired/wrong-user token.","commonSituations":"Client submits with an old userTask id after re-applying; multi-account login mixup sends another user's token; id confusion between the task id and the userTask id (they are different documents).","solutions":["Use the userTask id (from the apply response / user task list), not the task id","Ensure the Authorization token belongs to the same user as the userTask record","Re-fetch the user's task list to confirm the record still exists before submitting","Check the id string is not truncated or trimmed incorrectly on the client"],"exampleFix":"// before\nawait api.submitTask(task.id, data) // wrong id: task id, not userTask id\n// after\nconst userTask = await api.getUserTaskList().then(l => l.find(t => t.taskId === task.id))\nawait api.submitTask(userTask.id, data)","handlingStrategy":"try-catch","validationCode":"const userTasks = await api.getUserTaskList(token.id)\nconst ut = userTasks.find(t => t.id === userTaskId && t.userId === token.id)\nif (!ut) throw new Error('userTask does not exist or is not owned by the current user')","typeGuard":"function isOwnUserTask(ut: UserTask | null, userId: string): ut is UserTask {\n  return !!ut && ut.userId.toString() === userId\n}","tryCatchPattern":"try {\n  await api.submitTask(userTaskId, data)\n} catch (e) {\n  if (e?.errCode === '60010') {\n    // wrong id or wrong token user: re-fetch user task list with the current token\n  } else throw e\n}","preventionTips":["Distinguish task id vs userTask id in client models","Never reuse tokens across accounts in multi-account flows","Refresh the user task list after apply to get the authoritative userTask id"],"tags":["http-404","authorization","ownership-check"],"backgroundTag":"resource-not-found","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}