yikart/AiToEarn · error · BadRequestException

初始化失败,缺少必要的上传参数

Error message

初始化失败,缺少必要的上传参数

What it means

Thrown by uploadAndPublishVideo (tiktok.service.ts:522) after initVideoPublish returns a result that lacks either publish_id or upload_url. The TikTok Content Posting API's init endpoint (/v2/post/publish/video/init/) is expected to return both a publish_id and a chunked upload URL; if either is missing, the three-step upload cannot proceed. This is a defensive invariant check against malformed/unexpected TikTok API responses.

Source

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

      description?: string;
      privacyStatus?: string;
      disableComment?: boolean;
      disableDuet?: boolean;
      disableStitch?: boolean;
      videoCoverTimestampMs?: number;
      tags?: string[];
    },
    pollInterval: number = 2000,  
    maxRetries: number = 30
  ): Promise<any> {
    try {
      // 1. 第一步:初始化视频发布
      this.logger.debug('第一步:初始化视频发布...');
      const videoSize = videoBuffer.length;
      const initResult = await this.initVideoPublish(accessToken, videoSize, videoInfo);
      
      if (!initResult.publish_id || !initResult.upload_url) {
        throw new BadRequestException('初始化失败,缺少必要的上传参数');
      }
      
      const { publish_id } = initResult;
      
      // 2. 第二步:上传视频文件
      this.logger.debug(`第二步:上传视频文件,publish_id: ${publish_id}...`);
      await this.directUploadVideo(accessToken, videoBuffer, initResult);
      
      // 3. 第三步:轮询视频发布状态 // 每分钟不超过30次
      this.logger.debug(`第三步:轮询视频发布状态,publish_id: ${publish_id}...`);
      
      // 存储发布记录
      const maxRecord = await this.pubRecordModel.findOne().sort({ id: -1 });
      const newId = maxRecord ? maxRecord.id + 1 : 1;
      
      const pubRecord = await this.pubRecordModel.create({
        id: newId,
        userId,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Log the full initResult before the throw to see exactly which field is missing and what TikTok actually returned.
  2. Verify the access token has video.publish and video.upload scopes and that the user re-authorized after scope changes.
  3. Confirm videoSize (videoBuffer.length) is within TikTok's accepted range (non-zero, under the max) before calling init.
  4. Check that initVideoPublish targets the correct endpoint and parses data.data from the response, not data.
  5. Add explicit handling for TikTok's partial-success/error codes in the init response body.

Example fix

// before
if (!initResult.publish_id || !initResult.upload_url) {
  throw new BadRequestException('初始化失败,缺少必要的上传参数');
}
// after
this.logger.warn(`initVideoPublish result: ${JSON.stringify(initResult)}`);
if (!initResult?.publish_id) {
  throw new BadRequestException(`初始化失败:缺少 publish_id(响应: ${JSON.stringify(initResult)})`);
}
if (!initResult?.upload_url) {
  throw new BadRequestException(`初始化失败:缺少 upload_url(响应: ${JSON.stringify(initResult)}`);
}
Defensive patterns

Strategy: validation

Validate before calling

const init = await tiktokService.initVideoPublish(token, buffer.length, info);
if (!init?.publish_id || !init?.upload_url) {
  throw new Error(`init incomplete: publish_id=${!!init?.publish_id}, upload_url=${!!init?.upload_url}, raw=${JSON.stringify(init)}`);
}

Type guard

function hasInitFields(r: unknown): r is { publish_id: string; upload_url: string } {
  const o = r as any;
  return !!o && typeof o.publish_id === 'string' && o.publish_id.length > 0
    && typeof o.upload_url === 'string' && o.upload_url.length > 0;
}

Try / catch

try {
  await tiktokService.uploadAndPublishVideo(token, userId, accountId, buffer, info);
} catch (e) {
  if (e.message.includes('缺少必要的上传参数')) {
    // re-auth scopes / inspect init response, then retry once
  } else throw e;
}

Prevention

When it happens

Trigger: TikTok's /v2/post/publish/video/init/ responds 2xx but the body's data object omits publish_id or upload_url — e.g. when the app lacks the video.publish scope, the file size exceeds the allowed range, the draft/PULL_FROM_URL vs FILE_UPLOAD mode is mismatched, or the access token's user has not authorized video posting.

Common situations: Apps approved without the video.upload/video.publish scopes hitting init with a valid-looking 200; oversized or zero-length video buffers rejected silently; TikTok API version drift changing response field names (e.g. data nested differently); sandbox vs production environment differences in returned fields.

Related errors


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