yikart/AiToEarn · error · BadRequestException

无效的视频上传结果,缺少视频ID

Error message

无效的视频上传结果,缺少视频ID

What it means

Thrown by publishVideo (tiktok.service.ts:631) when the uploadResult passed in contains neither video_id nor init_data.video_id. publishVideo is step two of the legacy publish flow: it needs the video id produced by the upload step to attach to the /v2/video/publish/ call. An uploadResult missing these fields means the preceding upload did not actually yield a usable video.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.service.ts:631

   * 发布视频(原始方式)
   * @param accessToken 访问令牌
   * @param userId 用户ID
   * @param accountId TikTok账号ID
   * @param videoDto 视频发布参数
   * @param uploadResult 上传结果,包含视频ID和初始化数据
   * @returns 发布结果
   */
  async publishVideo(
    accessToken: string,
    userId: string,
    accountId: string,
    videoDto: CreateVideoDto,
    uploadResult: any
  ): Promise<any> {
    try {
      const videoId = uploadResult.video_id || (uploadResult.init_data?.video_id);
      if (!videoId) {
        throw new BadRequestException('无效的视频上传结果,缺少视频ID');
      }

      const params: any = {
        video_id: videoId,
        text: videoDto.description,
        disable_comment: false,
        disable_duet: false,
        privacy_level: videoDto.private ? 'private' : 'public'
      };

      if (videoDto.hashtags && videoDto.hashtags.length > 0) {
        // 添加话题标签
        const hashtags = videoDto.hashtags.map(tag => `#${tag.replace(/^#/, '')}`).join(' ');
        params.text = `${params.text} ${hashtags}`;
      }

      // 如果有初始化数据,添加必要的发布参数
      if (uploadResult.init_data && uploadResult.init_data.publish_params) {

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Inspect the actual uploadResult object (log it) to find where the video id really lives and pass that shape.
  2. Ensure you pass response.data of the upload call, not the Axios response wrapper.
  3. Check the upload step's success status before calling publishVideo; abort if it reported failure.
  4. Align the upload method with the legacy flow expected by publishVideo, or switch entirely to the three-step uploadAndPublishVideo.
  5. Validate uploadResult in the caller before invoking publishVideo to fail earlier with a clearer message.

Example fix

// before
await tiktokService.publishVideo(token, userId, accountId, dto, uploadResponse);
// after
const uploadData = uploadResponse?.data?.data ?? uploadResponse?.data;
if (!uploadData?.video_id && !uploadData?.init_data?.video_id) {
  throw new Error(`upload returned no video_id: ${JSON.stringify(uploadData)}`);
}
await tiktokService.publishVideo(token, userId, accountId, dto, uploadData);
Defensive patterns

Strategy: type-guard

Validate before calling

const vid = uploadResult?.video_id ?? uploadResult?.init_data?.video_id;
if (!vid) {
  throw new Error(`no video_id in upload result: ${JSON.stringify(uploadResult)}`);
}

Type guard

function hasVideoId(r: unknown): r is { video_id?: string; init_data?: { video_id: string } } {
  const o = r as any;
  return typeof o?.video_id === 'string' && o.video_id.length > 0
    || typeof o?.init_data?.video_id === 'string' && o.init_data.video_id.length > 0;
}

Try / catch

try {
  await tiktokService.publishVideo(token, userId, accountId, dto, uploadResult);
} catch (e) {
  if (e.message.includes('缺少视频ID')) {
    logger.error('upload result shape mismatch', uploadResult);
    // fix normalization of the upload response, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Caller passes the raw response of a failed or differently-shaped upload (e.g. { success: true } with no data, or a direct-upload response whose id lives under data.data.video_id), so uploadResult.video_id and uploadResult.init_data?.video_id are both undefined.

Common situations: Mixing responses between the new three-step API and the legacy upload flow; passing the whole Axios response instead of response.data; upload actually failed upstream but its error was swallowed; TikTok response-shape changes nesting video_id differently.

Related errors


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