yikart/AiToEarn · error · AppException
InvalidAiTaskId
InvalidAiTaskId
Error message
ResponseCode.InvalidAiTaskId
What it means
InvalidAiTaskId thrown in transformToCommonResponse when a video AI log is in a terminal/succeeded state (not Generating, not Failed) but has no `response` payload stored. The task cannot be mapped to a common response because the provider result is missing, and the service reports this as an invalid/unusable task record.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/video/video.service.ts:186
const finishedAt = aiLog.duration
? new Date(aiLog.startedAt.getTime() + aiLog.duration)
: undefined
if (aiLog.status === AiLogStatus.Failed) {
return {
...base,
status: TaskStatus.Failure,
videoUrl: undefined,
coverUrl: savedMedia.coverUrl ? FileUtil.buildUrl(savedMedia.coverUrl) : undefined,
mediaId: savedMedia.mediaId,
groupId: savedMedia.groupId,
error: { message: aiLog.errorMessage ?? 'Video task failed' },
finishedAt,
}
}
if (!aiLog.response) {
throw new AppException(ResponseCode.InvalidAiTaskId)
}
const channelResult = this.getChannelTaskResult(aiLog)
return {
...base,
...channelResult,
coverUrl: savedMedia.coverUrl ? FileUtil.buildUrl(savedMedia.coverUrl) : undefined,
mediaId: savedMedia.mediaId,
groupId: savedMedia.groupId,
finishedAt,
}
}
async ensureSavedMediaByAiLogId(aiLogId: string): Promise<void> {
const aiLog = await this.aiLogRepo.getById(aiLogId)
if (!aiLog || aiLog.type !== AiLogType.Video) {
returnView on GitHub (pinned to d3aa8bea5b)
Solutions
- Verify the task id is correct and re-query — if the log was mid-write the response may appear shortly after.
- Inspect the aiLog document in MongoDB: check `status` vs presence of `response` to confirm data corruption.
- Trigger the status sync/callback path (ensureSavedVideoMedia / channel refresh) to backfill the response, or mark the log Failed so the failure branch returns instead of throwing.
- Fix the callback handler so `response` is saved atomically with the status change.
Example fix
// before
if (aiLog.status === 'success') return transformToCommonResponse(aiLog) // throws if response missing
// after
if (aiLog.status === 'success' && !aiLog.response) {
return { status: TaskStatus.Failure, error: { message: 'provider response missing' } }
} Defensive patterns
Strategy: try-catch
Try / catch
try {
const res = await videoService.getVideoTaskStatus({ taskId })
} catch (e) {
if (e instanceof AppException && e.code === 'InvalidAiTaskId') {
// treat as unrecoverable record; surface 'task record incomplete' to caller or re-sync from provider
}
} Prevention
- Persist provider `response` atomically with status transitions in callbacks.
- Add a periodic reconciliation job that refetches provider status for logs missing response.
- Monitor for aiLogs with terminal status and null response.
When it happens
Trigger: Querying getVideoTaskStatus or listVideoTasks for a task whose aiLog reached a non-generating, non-failed status without a persisted provider `response` — e.g. status set to success by a callback that did not save the response body, or a log partially written.
Common situations: Provider callback succeeded but response-saving step failed or was skipped; data migration dropped the response field; task record manually edited in MongoDB; querying right at a race where status flipped but response write is pending.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/349b44bfd58d30f8.
Report an issue: GitHub.