jackwener/OpenCLI · error · CommandExecutionError

提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}

Error message

提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}

What it means

commitVideoUploadInner POSTs CommitUploadInner and expects a JSON body; this error fires when JSON.parse fails on the response text, including the HTTP status and the first 300 characters of the raw body. It indicates the commit endpoint returned HTML, an empty body, or another non-JSON payload instead of the expected API envelope.

Source

Thrown at clis/douyin/_shared/vod-upload.js:193

  const params = new URLSearchParams({
    Action: 'CommitUploadInner',
    Version: '2020-11-19',
    SpaceName: VOD_SPACE_NAME,
  });
  const url = `${VOD_UPLOAD_HOST}?${params.toString()}`;
  const body = JSON.stringify({ SessionKey: uploadInfo.session_key });
  const headers = computeAws4Headers(url, credentials, {
    method: 'POST',
    body,
    headers: { 'content-type': 'application/json;charset=UTF-8' },
  });
  const res = await fetch(url, { method: 'POST', headers, body, signal: AbortSignal.timeout(30000) });
  const text = await res.text();
  let payload;
  try {
    payload = JSON.parse(text);
  } catch {
    throw new CommandExecutionError(`提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}`);
  }
  const error = payload?.ResponseMetadata?.Error;
  if (!res.ok || error) {
    throw new CommandExecutionError(`提交抖音上传失败: HTTP ${res.status} ${JSON.stringify(error ?? payload)}`);
  }
  const result = payload?.Result?.Results?.[0] ?? payload?.Result ?? {};
  const videoId = result.Vid ?? result.VideoId ?? result.VideoID ?? result.vid ?? uploadInfo.video_id;
  if (!videoId) {
    throw new CommandExecutionError(`提交抖音上传响应缺少 video id: ${JSON.stringify(payload).slice(0, 500)}`);
  }
  const meta = result.Meta ?? result.VideoMeta ?? {};
  return {
    video_id: videoId,
    poster_uri: result.PosterUri ?? result.PosterURI ?? result.SnapshotUri ?? result.SnapshotURI ?? '',
    width: Number(meta.Width ?? meta.width ?? 720) || 720,
    height: Number(meta.Height ?? meta.height ?? 1280) || 1280,
    raw: result,
  };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the body snippet in the message — HTML suggests login/WAF issues; re-authenticate or complete verification and retry.
  2. Refresh STS credentials via getUploadAuthV5Credentials and re-run commit if the token expired.
  3. Retry with backoff for 5xx statuses — gateway failures are often transient.
  4. Bypass VPN/proxy to rule out response rewriting by middleboxes.
  5. Note that the upload itself may still have succeeded even if commit failed non-JSON; check the video id on the platform before re-uploading.

Example fix

// before
let payload;
try {
  payload = JSON.parse(text);
} catch {
  throw new CommandExecutionError(`提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}`);
}
// after
let payload;
try {
  payload = JSON.parse(text);
} catch {
  if (res.status >= 500) return retryCommitWithBackoff(); // transient gateway failure
  throw new CommandExecutionError(`提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// refresh credentials if expired before committing
if (credentials.expired_time && credentials.expired_time * 1000 < Date.now()) {
  credentials = await getUploadAuthV5Credentials(page);
}

Type guard

null

Try / catch

try {
  return await commitVideoUploadInner(uploadInfo, creds);
} catch (e) {
  if (/非 JSON 响应/.test(e.message)) {
    if (/HTTP 5\d\d/.test(e.message)) { await sleep(3000); return retry(); }
    if (/<html/i.test(e.message)) throw new AuthRequiredError('creator.douyin.com', e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: The CommitUploadInner fetch returns non-JSON: WAF/CAPTCHA HTML page, gateway 502/504 error page, empty body, or a redirect to login due to expired credentials.

Common situations: Expired STS token causing edge errors; risk-control interception of the commit request; transient CDN/edge failures; proxy/VPN middleboxes altering the response; Douyin endpoint changes.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/80213d13a4db33c7. Report an issue: GitHub.