yikart/AiToEarn · error · AppHttpException

ErrHttpBack.task_no_material

ErrHttpBack.task_no_material

Error message

task_no_material

What it means

AppHttpException with ErrHttpBack.task_no_material (errCode 90000, message '该任务没有添加素材'). Thrown by AdminTaskService.updateStatus (adminTask.service.ts:108) when an admin activates (status=TaskStatus.ACTIVE) a task of type TaskType.ARTICLE but no TaskMaterial document exists for that taskId. ARTICLE tasks must carry at least one material before going live.

Source

Thrown at project/aitoearn-electron/server/src/modules/task/adminTask.service.ts:108

    const updatedTask = await this.taskModel.findByIdAndUpdate(id, data).exec();
    if (!updatedTask) throw new NotFoundException('Task not found');
    return updatedTask;
  }

  /**
   * 更新任务状态
   * @param task
   * @param status
   * @returns
   */
  async updateStatus(task: Task, status: TaskStatus): Promise<Task> {
    if (status === TaskStatus.ACTIVE && task.type === TaskType.ARTICLE) {
      // 查询是否存在任务的素材
      const material = await this.taskMaterialModel.findOne({
        taskId: task.id,
      });

      if (!material) throw new AppHttpException(ErrHttpBack.task_no_material);
    }

    const res = await this.taskModel.findByIdAndUpdate(
      { _id: task.id },
      {
        status,
      },
    );

    return res;
  }

  /**
   * 更新任务状态
   * @param id
   * @param status
   * @returns
   */

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Add at least one task material for the task (admin material creation endpoint) before activating it
  2. Verify a material exists: query materials with filter { taskId } and create one if empty
  3. If the task should not require material, change its type away from ARTICLE
  4. Check the material's taskId field actually references this task (not another task's id)

Example fix

// before
await adminTaskApi.updateStatus(taskId, 'ACTIVE') // throws 90000
// after
await adminTaskApi.createTaskMaterial({ taskId, ...material })
await adminTaskApi.updateStatus(taskId, 'ACTIVE')
Defensive patterns

Strategy: validation

Validate before calling

const material = await adminTaskApi.findTaskMaterial({ taskId })
if (!material && task.type === 'ARTICLE') {
  throw new Error('Cannot activate ARTICLE task without material')
}

Type guard

function canActivate(task: Task, materials: TaskMaterial[]): boolean {
  return task.type !== 'ARTICLE' || materials.length > 0
}

Try / catch

try {
  await adminTaskApi.updateStatus(taskId, 'ACTIVE')
} catch (e) {
  if (e?.errCode === '90000') {
    // create a material for the task, then retry activation
  } else throw e
}

Prevention

When it happens

Trigger: Admin PATCH/POST to update a task's status to ACTIVE where task.type === ARTICLE and taskMaterialModel.findOne({ taskId }) returns null — the article task was created without uploading/attaching material.

Common situations: Admin forgets to add material in the admin panel; material was deleted after task creation; task type later switched to ARTICLE without adding material; wrong taskId linkage between task and material collections.

Related errors


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