jackwener/OpenCLI · error · CommandExecutionError
提交抖音上传失败: HTTP ${res.status} ${JSON.stringify(error ?? paylo
Error message
提交抖音上传失败: HTTP ${res.status} ${JSON.stringify(error ?? payload)} What it means
Thrown by commitVideoUploadInner after calling the Douyin VOD CommitUploadInner API when the HTTP response is not OK or the JSON payload contains ResponseMetadata.Error. It wraps the full API error object so the developer can see why the commit failed (signature, session, or space problems). The library throws it because a non-ok commit means the uploaded video will never become a playable Vid.
Source
Thrown at clis/douyin/_shared/vod-upload.js:197
});
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
- Inspect the embedded ResponseMetadata.Error.Code in the message and match it against VodSpace/InvalidParameter errors
- Re-run the upload from scratch to get a fresh SessionKey and commit promptly
- Verify VOD access key/secret and VOD_SPACE_NAME env/config values
- Check system clock skew if signature-related errors appear
- Retry after a short delay if the status is 5xx/rate-limit
Example fix
// before: commit long after upload finished, session expired await uploadChunks(...); await sleep(600000); await commitVideoUploadInner(info, creds); // after: commit immediately after upload await uploadChunks(...); const result = await commitVideoUploadInner(info, creds);
Defensive patterns
Strategy: try-catch
Validate before calling
if (!process.env.VOD_ACCESS_KEY || !process.env.VOD_SECRET_KEY) throw new Error('VOD credentials missing');
if (!uploadInfo?.session_key) throw new Error('session_key missing; re-run upload'); Type guard
function isVodError(payload) {
return Boolean(payload?.ResponseMetadata?.Error);
} Try / catch
try {
const committed = await commitVideoUploadInner(info, creds);
} catch (e) {
if (/提交抖音上传失败/.test(e.message)) {
console.error('commit rejected:', e.message);
// re-upload + retry once with fresh session
} else throw e;
} Prevention
- Commit immediately after the last chunk uploads to avoid SessionKey expiry
- Validate VOD access key/secret/space config at startup
- Log ResponseMetadata.Error.Code to build a retry table for known codes
- Keep system clock in sync for AWS4 signatures
When it happens
Trigger: Calling commitVideoUploadInner with an expired/invalid SessionKey; wrong AWS4 credentials (access key/secret) so the VOD API rejects signature; VOD_SPACE_NAME not existing or unauthorized; the chunked upload never completed so CommitUploadInner rejects the session; transient VOD 5xx responses.
Common situations: Expired Volcano/ByteDance VOD credentials in env config; uploading a file then committing after session timeout; misconfigured space name after a Douyin backend change; clock skew invalidating AWS4 signature.
Related errors
- 提交抖音上传响应缺少 video id: ${JSON.stringify(payload).slice(0, 500)
- ${action}失败: ${JSON.stringify(error)}
- Cover image file not found: ${imagePath}
- ImageX upload failed with status ${res.status}: ${body}
- TOS init multipart upload failed with status ${res.status}:
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/83acc4a331d78ae5.
Report an issue: GitHub.