yikart/AiToEarn · error · AppException

AgentTaskNotFound

AgentTaskNotFound

Error message

AgentTaskNotFound

What it means

initializeTask in agent-runtime.service.ts resumes an existing agent conversation: it loads the original task by id AND userId via contentGenerateRepository.getByUserIdAndId. If no task is found, it throws AppException(ResponseCode.AgentTaskNotFound). This means the given originalTaskId does not exist or does not belong to the requesting user.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/agent/services/agent-runtime.service.ts:726

    sessionId: string | undefined
    historicalMessages: Array<Record<string, unknown>>
    abortController: AbortController
    mcpServers: Record<string, McpServerConfig>
  }> {
    let task
    let originalTask
    let sessionId: string | undefined
    let historicalMessages: Array<Record<string, unknown>> = []

    if (dto.taskId) {
      const originalTaskId = dto.taskId
      this.logger.debug({ taskId: originalTaskId }, `Resuming conversation for task ${originalTaskId}`)

      originalTask = await this.contentGenerateRepository.getByUserIdAndId(userId, originalTaskId)
      if (!originalTask) {
        this.logger.warn({ taskId: originalTaskId }, `Task ${originalTaskId} not found for user ${userId}`)
        throw new AppException(ResponseCode.AgentTaskNotFound)
      }

      sessionId = originalTask.sessionId
      if (!sessionId) {
        this.logger.warn({ taskId: originalTaskId }, `Task ${originalTaskId} has no sessionId, cannot resume`)
        throw new AppException(ResponseCode.AgentTaskNotFound)
      }

      this.logger.debug({ taskId: originalTaskId, sessionId }, `Task ${originalTaskId} resuming with sessionId: ${sessionId}`)
      task = originalTask
      historicalMessages = originalTask.messages || []

      await this.downloadAgentSession(originalTask)
    }
    else {
      task = await this.contentGenerateRepository.create({
        userId,
      })
      this.logger.debug({ taskId: task.id }, `Created new task ${task.id} for user ${userId}`)

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Verify the originalTaskId exists in the content-generate collection for that exact userId; re-query with the same credentials
  2. If the task was deleted or from another environment, start a fresh task instead of resuming
  3. Check the client is not sending a stale/cached taskId after re-login or DB reset
  4. Confirm the userId resolved from the auth token matches the task owner

Example fix

// before
originalTask = await this.contentGenerateRepository.getByUserIdAndId(userId, originalTaskId)
if (!originalTask) throw new AppException(ResponseCode.AgentTaskNotFound)
// after
if (!ObjectId.isValid(originalTaskId)) throw new AppException(ResponseCode.AgentTaskNotFound)
originalTask = await this.contentGenerateRepository.getByUserIdAndId(userId, originalTaskId)
if (!originalTask) throw new AppException(ResponseCode.AgentTaskNotFound)
Defensive patterns

Strategy: validation

Validate before calling

// client-side pre-check before resuming
if (!originalTaskId || !originalTaskId.trim()) throw new Error('originalTaskId is required to resume');
// server-side: validate id shape before the DB query
if (!ObjectId.isValid(originalTaskId)) throw new AppException(ResponseCode.AgentTaskNotFound);

Type guard

function isOwnTask(task: { userId: string } | null, userId: string): task is { userId: string } {
  return task !== null && task.userId === userId;
}

Try / catch

try {
  await aiService.createContentGenerationTask({ originalTaskId });
} catch (e) {
  if (e instanceof AppException && e.code === ResponseCode.AgentTaskNotFound) {
    // fall back to starting a new task instead of resuming
  } else throw e;
}

Prevention

When it happens

Trigger: createContentGenerationTask is called with a continuation/originalTaskId that (a) was never created, (b) was deleted, (c) has a different userId (wrong user's token), or (d) contains a malformed/foreign-namespace id.

Common situations: Client cached a taskId from a cleared database/environment (dev vs prod); calling resume with a task id from another account after switching users; id truncation or wrong field passed by the frontend.


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