jackwener/OpenCLI · error · CommandExecutionError
解析抖音上传授权失败: ${error instanceof Error ? error.message : Strin
Error message
解析抖音上传授权失败: ${error instanceof Error ? error.message : String(error)} What it means
getUploadAuthV5Credentials JSON-parses the result.auth string into a credentials object; this error wraps the JSON.parse failure. It means auth existed but was not valid JSON — truncated content, HTML injected into the response, or an encoded format change. The parse error message is included verbatim.
Source
Thrown at clis/douyin/_shared/vod-upload.js:116
const result = unwrapEvaluateResult(await page.evaluate(`fetch(${JSON.stringify(AUTH_V5_URL)}, { credentials: 'include' }).then(r => r.json())`));
if (!result || Array.isArray(result) || typeof result !== 'object') {
throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);
}
if (result.status_code !== 0) {
const message = result.status_msg ?? result.message ?? 'unknown error';
if (result.status_code === 401 || result.status_code === 403 || /login|cookie|auth|captcha|verify|forbidden|permission|登录|登陆|权限|验证|验证码/i.test(String(message))) {
throw new AuthRequiredError('creator.douyin.com', `获取抖音上传授权失败: ${message}`);
}
throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);
}
if (!result.auth) {
throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);
}
let auth;
try {
auth = JSON.parse(result.auth);
} catch (error) {
throw new CommandExecutionError(`解析抖音上传授权失败: ${error instanceof Error ? error.message : String(error)}`);
}
if (!auth.AccessKeyID || !auth.SecretAccessKey || !auth.SessionToken) {
throw new CommandExecutionError('抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken');
}
return {
access_key_id: auth.AccessKeyID,
secret_access_key: auth.SecretAccessKey,
session_token: auth.SessionToken,
user_id: extractUserIdFromSessionToken(auth.SessionToken),
expired_time: auth.ExpiredTime,
current_time: auth.CurrentTime,
};
}
export async function applyVideoUploadInner(fileSize, credentials) {
const params = new URLSearchParams({
Action: 'ApplyUploadInner',
Version: '2020-11-19',View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw auth string (first bytes) to see what was actually returned — HTML signals a login/redirect problem, so re-login.
- Re-login to creator.douyin.com and retry if the payload looks like a login page.
- If the content is base64/URL-encoded, decode before JSON.parse and update the code accordingly.
- Check for proxies, VPNs, or extensions altering page network responses.
- Retry on a fresh page load to rule out a corrupted intermediate response.
Example fix
// before
auth = JSON.parse(result.auth);
// after
let raw = result.auth;
if (/^STS?[0-9]/.test(raw) || /^[A-Za-z0-9+/=]+$/.test(raw)) {
raw = Buffer.from(raw, 'base64').toString('utf8'); // decode before parse if encoded
}
auth = JSON.parse(raw); Defensive patterns
Strategy: validation
Validate before calling
function looksLikeJsonAuth(s) {
return typeof s === 'string' && s.trim().startsWith('{');
}
// before relying on result.auth:
if (!looksLikeJsonAuth(result.auth)) throw new Error('auth 字段不是 JSON 字符串'); Type guard
null
Try / catch
try {
auth = JSON.parse(result.auth);
} catch (error) {
console.error('原始 auth 内容:', String(result.auth).slice(0, 200));
throw error; // HTML content => re-login path; encoded content => decode path
} Prevention
- Log the first bytes of result.auth on failure to identify HTML vs encoded payloads.
- Re-login when the payload looks like an HTML login/redirect page.
- Keep the page free of extensions/proxies that can rewrite network responses.
- Check for Douyin encoding changes after app updates.
When it happens
Trigger: result.auth contains non-JSON text: an HTML error/login page snippet, URL-encoded or base64 content, or a truncated string from an interrupted response.
Common situations: A captive portal or proxy replaced the response with HTML; Douyin changed the auth encoding (e.g. now base64 instead of JSON string); cookie-consent/login redirect HTML captured by the in-page fetch.
Related errors
- 申请抖音上传地址失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300
- 提交抖音上传失败,非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}
- File could not be decoded as UTF-8 text: ${path}
- Bilibili conclusion API returned malformed model_result JSON
- Boss API request failed: ${message}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/462e130ddb64d694.
Report an issue: GitHub.