{"record":{"id":"3d34d4f1c402ed54","repo":"yikart/AiToEarn","slug":"invalidaitaskid-3d34d4","errorCode":"InvalidAiTaskId","errorMessage":"InvalidAiTaskId","messagePattern":"InvalidAiTaskId","errorType":"error_code","errorClass":"AppException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/openai/openai.service.ts","lineNumber":133,"sourceCode":"      status: AiLogStatus.Generating,\n    })\n\n    return {\n      ...result,\n      id: aiLog.id,\n    }\n  }\n\n  /**\n   * OpenAI 视频 Remix\n   */\n  async remixVideo(request: UserOpenAIVideoRemixRequestDto) {\n    const { userId, userType, videoId, prompt } = request\n\n    // 首先查找原视频任务\n    const aiLog = await this.aiLogRepo.getByIdAndUserId(videoId, userId, userType)\n    if (!aiLog || aiLog.channel !== AiLogChannel.OpenAI || !aiLog.taskId) {\n      throw new AppException(ResponseCode.InvalidAiTaskId)\n    }\n\n    const model = aiLog.model\n\n    const startedAt = new Date()\n    const result = await this.aiAvailability.executeAsync(\n      { provider: 'openai', operation: 'videoGeneration', model },\n      () => this.openaiLibService.remixVideo(aiLog.taskId!, prompt),\n      r => r.id,\n    )\n\n    const newAiLog = await this.aiLogRepo.create({\n      userId,\n      userType,\n      taskId: result.id,\n      model,\n      channel: AiLogChannel.OpenAI,\n      startedAt,","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/openai/openai.service.ts#L115-L151","documentation":"remixVideo looks up the original video task with aiLogRepo.getByIdAndUserId(videoId, userId, userType) and requires an existing log whose channel is OpenAI and which has a non-empty taskId. If the log is missing, belongs to another user, has a different channel (e.g. Veo), or lacks a provider taskId, it throws AppException(ResponseCode.InvalidAiTaskId).","triggerScenarios":"Calling remixVideo with a videoId that (a) does not exist, (b) belongs to a different userId/userType, (c) was created via a non-OpenAI channel, or (d) has no OpenAI taskId stored (task creation never completed).","commonSituations":"Client passes the internal aiLog id from another provider's generation; user A tries to remix user B's video; the original generation failed before a provider taskId was persisted; stale/cached videoId after database cleanup.","solutions":["Pass a valid OpenAI-channel videoId owned by the requesting user","Verify the original video task completed creation and has a stored taskId (query the ai_log collection)","Check userId/userType match the owner of the original task"],"exampleFix":"// before\nremixVideo({ videoId: veoTaskLogId, ... }) // wrong channel\n// after\nconst log = await aiLogRepo.getByIdAndUserId(videoId, userId, userType)\nif (log?.channel === AiLogChannel.OpenAI && log.taskId) { await remixVideo({ videoId, ... }) }","handlingStrategy":"validation","validationCode":"const log = await aiLogRepo.getByIdAndUserId(videoId, userId, userType)\nif (!log || log.channel !== AiLogChannel.OpenAI || !log.taskId) {\n  throw new Error('Video is not a remixable OpenAI task for this user')\n}","typeGuard":"function isRemixableOpenAILog(log: AiLog | null): log is OpenAIVideoAiLog & { taskId: string } {\n  return !!log && log.channel === AiLogChannel.OpenAI && typeof log.taskId === 'string' && log.taskId.length > 0\n}","tryCatchPattern":"try {\n  await openaiVideoService.remixVideo({ videoId, prompt })\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.InvalidAiTaskId) {\n    // surface 'original video not found or not remixable' to the caller\n  }\n}","preventionTips":["Only offer remix on videos generated via the OpenAI channel","Check taskId exists on the source log before showing remix UI","Ensure the videoId used is the internal aiLog id owned by the current user"],"tags":["task-id","openai","validation","not-found","video-remix"],"backgroundTag":"invalid-ai-task-id","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}