yikart/AiToEarn · warning · AppException

AiCallFailed

AiCallFailed

Error message

Missing usage metadata

What it means

postComment validates TikTokCommentDto fields accountId, videoId and text; any missing/empty field throws BadRequestException('accountId, videoId和text是必须的'). All three are needed to resolve the token, target video, and comment content.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/chat/chat.service.ts:143

  }

  async chatCompletion(request: ChatCompletionDto, userId: string) {
    const { messages, model, ...params } = request

    const langchainMessages: BaseMessage[] = messages.map((message) => {
      return new ChatMessage(message)
    })

    const result = await this.openaiService.createChatCompletion({
      model,
      messages: langchainMessages,
      ...params,
      modalities: params.modalities as OpenAIClient.Chat.ChatCompletionModality[],
    })

    const usage = result.usage_metadata
    if (!usage) {
      throw new AppException(ResponseCode.AiCallFailed, { error: 'Missing usage metadata' })
    }

    // 处理返回的 content 中的 base64 图片
    result.content = await this.processAIMessageChunkContent(result.content, model, userId) as typeof result.content

    return {
      model,
      usage,
      ...result,
    }
  }

  private async handleCompletion(
    params: ChatCompletionDto,
    userId: string,
    userType: UserType,
    modelConfig: { name: string, channel: AiLogChannel },
    startedAt: Date,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Send { accountId, videoId, text } with non-empty text in the JSON body.
  2. Disable the submit button until text.trim().length > 0 client-side.
  3. Verify the DTO key is exactly 'text' matching TikTokCommentDto.

Example fix

// before
await api.post('/plat/tiktok/video/comment', { accountId, videoId, text });
// after
if (!accountId || !videoId || !text?.trim()) return;
await api.post('/plat/tiktok/video/comment', { accountId, videoId, text: text.trim() });
Defensive patterns

Strategy: validation

Validate before calling

if (!commentDto.accountId || !commentDto.videoId || !commentDto.text?.trim()) throw new Error('accountId, videoId和text是必须的');

Type guard

function isCommentDto(v): v is { accountId: string; videoId: string; text: string } {
  const d = v as any;
  return typeof d?.accountId === 'string' && d.accountId.length > 0 && typeof d?.videoId === 'string' && d.videoId.length > 0 && typeof d?.text === 'string' && d.text.trim().length > 0;
}

Try / catch

try {
  return await api.post('/plat/tiktok/video/comment', commentDto);
} catch (e) {
  if (e.response?.status === 400) console.error('评论请求缺少 accountId/videoId/text');
  throw e;
}

Prevention

When it happens

Trigger: POST the comment route with a TikTokCommentDto body where accountId, videoId or text is absent or an empty string (e.g. submitting the comment box without typing text).

Common situations: User submits an empty comment and the frontend doesn't block it, comment payload built from a context missing the account, or DTO field name mismatch (comment vs text) leaving text undefined.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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