yikart/AiToEarn · error · BadRequestException

初始化响应缺少 publish_id 或 upload_url

Error message

初始化响应缺少 publish_id 或 upload_url

What it means

uploadVideoChunked validates the TikTok video-upload initialization response before sending chunks. TikTok's PULL/FILE_UPLOAD init API must return both a publish_id (identifies the publish task for later status polling) and an upload_url (the endpoint chunks are POSTed to). If either is missing or falsy, the service cannot proceed with the chunked upload and throws this BadRequestException at tiktok.service.ts:316.

Source

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

  }
  
  /**
   * 方式1:分片上传视频(POST方式)
   * @param accessToken 访问令牌
   * @param videoBuffer 视频文件缓冲区
   * @param initData 初始化返回的数据,包含 publish_id 和 upload_url
   * @returns 上传结果
   */
  private async uploadVideoChunked(
    accessToken: string,
    videoBuffer: Buffer,
    initData: any
  ): Promise<any> {
    try {
      const { publish_id, upload_url } = initData;
      
      if (!publish_id || !upload_url) {
        throw new BadRequestException('初始化响应缺少 publish_id 或 upload_url');
      }
      
      // 设置分片大小(每个分片5MB)
      const chunkSize = 5 * 1024 * 1024;
      const totalSize = videoBuffer.length;
      const totalChunkCount = Math.ceil(totalSize / chunkSize);
      
      this.logger.debug(`视频总大小: ${totalSize} 字节, 分片数: ${totalChunkCount}`);
      
      // 选择视频内容类型
      const contentType = 'video/mp4';
      
      // 存储每个分片的上传响应
      const uploadResponses = [];
      
      // 上传每个分片
      for (let i = 0; i < totalChunkCount; i++) {
        const start = i * chunkSize;

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Log the raw initData right before the call and verify the TikTok init endpoint actually returned publish_id and upload_url at the top level of the object.
  2. Check whether the init response nests fields (e.g. under data.data) and unwrap it before passing to uploadVideoChunked.
  3. Verify this.apiBaseUrl targets the correct TikTok environment (sandbox vs production) and a supported API version; re-run initVideoUpload to get a fresh upload URL.
  4. Add an explicit check of the init HTTP call's status/error_code before using its payload, so failed inits are surfaced as init errors rather than missing-field errors.

Example fix

// before
const { publish_id, upload_url } = initData;
if (!publish_id || !upload_url) {
  throw new BadRequestException('初始化响应缺少 publish_id 或 upload_url');
}
// after
const payload = initData?.data?.data ?? initData?.data ?? initData; // unwrap nested response
const { publish_id, upload_url } = payload ?? {};
if (!publish_id || !upload_url) {
  this.logger.error('TikTok init payload:', JSON.stringify(initData));
  throw new BadRequestException(`初始化响应缺少 publish_id 或 upload_url: ${JSON.stringify(initData).slice(0, 500)}`);
}
Defensive patterns

Strategy: validation

Validate before calling

function canChunkUpload(initData) {
  return !!initData && typeof initData.publish_id === 'string' && initData.publish_id.length > 0
    && typeof initData.upload_url === 'string' && initData.upload_url.startsWith('http');
}
if (!canChunkUpload(initData)) {
  initData = await initVideoUpload(accessToken, videoBuffer.length); // re-init before uploading
}

Type guard

function isInitData(v) {
  return typeof v === 'object' && v !== null
    && typeof (v as { publish_id?: unknown }).publish_id === 'string'
    && typeof (v as { upload_url?: unknown }).upload_url === 'string';
}

Try / catch

try {
  const result = await uploadVideo(accessToken, videoBuffer, initData);
} catch (e) {
  if (e.message.includes('初始化响应缺少')) {
    // re-run the TikTok init call and retry once with fresh initData
  } else throw e;
}

Prevention

When it happens

Trigger: uploadVideo → uploadVideoChunked is invoked with an initData object whose publish_id or upload_url is undefined/null/empty string — i.e. initVideoUpload received a TikTok init response that omitted these fields, was wrapped differently (e.g. data.data vs data), or returned an error payload that was not detected before calling uploadVideoChunked.

Common situations: TikTok API version drift (init response schema changed or fields renamed), wrong apiBaseUrl/environment (sandbox vs production returns different payloads), an init call that failed but whose error body was parsed as success, or caller-supplied initData that was constructed manually or cached stale.

Related errors


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