yikart/AiToEarn · error · BadRequestException

发布视频失败: ${error.response?.data?.error?.message || error.mess

Error message

发布视频失败: ${error.response?.data?.error?.message || error.message}

What it means

The outer catch of publishVideo (tiktok.service.ts:703-706). Any failure in the legacy publish flow — the video_id check (434), building params, the POST to the publish URL, or the Mongo record writes — is re-wrapped as BadRequestException('发布视频失败: ...') carrying the TikTok API error message or the original error message. The inner block already marks the publish record FAIL before rethrowing.

Source

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

          status: PubStatus.RELEASED,
          remoteId: data.data.share_id || videoId,
          updateTime: new Date()
        });

        return data.data;
      } catch (error) {
        // 更新发布记录为失败状态
        await this.pubRecordModel.findByIdAndUpdate(pubRecord._id, {
          status: PubStatus.FAIL,
          failReason: error.response?.data?.error?.message || error.message,
          updateTime: new Date()
        });

        throw error;
      }
    } catch (error) {
      this.logger.error('发布TikTok视频失败:', error.response?.data || error.message);
      throw new BadRequestException(`发布视频失败: ${error.response?.data?.error?.message || error.message}`);
    }
  }

  /**
   * 删除视频
   * @param accessToken 访问令牌
   * @param videoId 视频ID
   * @returns 删除结果
   */
  async deleteVideo(
    accessToken: string,
    videoId: string
  ): Promise<any> {
    try {
      const { data } = await firstValueFrom(
        this.httpService.post(`${this.apiBaseUrl}/v2/video/delete/`, {
          video_id: videoId
        }, {

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Check the '发布TikTok视频失败:' log line for error.response?.data — it contains TikTok's error code and log_id.
  2. Publish promptly after upload; if the error says the video is invalid/expired, re-upload and publish immediately.
  3. Refresh the access token and confirm the video.publish scope is granted.
  4. Validate params.text length and privacy_level values against TikTok constraints before the call.
  5. Check the publish record in Mongo — failReason was written there with the same message.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

const vid = uploadResult?.video_id ?? uploadResult?.init_data?.video_id;
if (!accessToken || !vid) throw new Error('token or video_id missing before publish');
const text = dto.description ?? '';
if (text.length + (dto.hashtags?.length ?? 0) > 2200) throw new Error('publish text exceeds TikTok limit');

Type guard

function isUpstreamHttpError(e: unknown): e is { response: { status: number; data: { error?: { message?: string } } } } {
  const o = e as any;
  return typeof o?.response?.status === 'number';
}

Try / catch

try {
  await tiktokService.publishVideo(token, userId, accountId, dto, uploadResult);
} catch (e) {
  if (isUpstreamHttpError(e) && e.response.status === 401) {
    // refresh token then retry once
  } else if (/invalid.*video/.test(e.message)) {
    // video expired: re-upload then publish immediately
  } else throw e;
}

Prevention

When it happens

Trigger: POST to /v2/video/publish/ (or init_data.publish_url) returns 4xx/5xx: invalid or expired access token, missing video.publish scope, invalid video_id (expired — TikTok video ids from upload expire quickly), text length/privacy_level violations, or DB write failures.

Common situations: Waiting too long between upload and publish so the uploaded video expires; app not approved for video publishing; text exceeding TikTok's character limits; using the wrong environment's token (China vs international endpoints).

Related errors


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