{"record":{"id":"462e130ddb64d694","repo":"jackwener/OpenCLI","slug":"error-instanceof-error-error-messa","errorCode":null,"errorMessage":"解析抖音上传授权失败: ${error instanceof Error ? error.message : String(error)}","messagePattern":"解析抖音上传授权失败: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/vod-upload.js","lineNumber":116,"sourceCode":"  const result = unwrapEvaluateResult(await page.evaluate(`fetch(${JSON.stringify(AUTH_V5_URL)}, { credentials: 'include' }).then(r => r.json())`));\n  if (!result || Array.isArray(result) || typeof result !== 'object') {\n    throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);\n  }\n  if (result.status_code !== 0) {\n    const message = result.status_msg ?? result.message ?? 'unknown error';\n    if (result.status_code === 401 || result.status_code === 403 || /login|cookie|auth|captcha|verify|forbidden|permission|登录|登陆|权限|验证|验证码/i.test(String(message))) {\n      throw new AuthRequiredError('creator.douyin.com', `获取抖音上传授权失败: ${message}`);\n    }\n    throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);\n  }\n  if (!result.auth) {\n    throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);\n  }\n  let auth;\n  try {\n    auth = JSON.parse(result.auth);\n  } catch (error) {\n    throw new CommandExecutionError(`解析抖音上传授权失败: ${error instanceof Error ? error.message : String(error)}`);\n  }\n  if (!auth.AccessKeyID || !auth.SecretAccessKey || !auth.SessionToken) {\n    throw new CommandExecutionError('抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken');\n  }\n  return {\n    access_key_id: auth.AccessKeyID,\n    secret_access_key: auth.SecretAccessKey,\n    session_token: auth.SessionToken,\n    user_id: extractUserIdFromSessionToken(auth.SessionToken),\n    expired_time: auth.ExpiredTime,\n    current_time: auth.CurrentTime,\n  };\n}\n\nexport async function applyVideoUploadInner(fileSize, credentials) {\n  const params = new URLSearchParams({\n    Action: 'ApplyUploadInner',\n    Version: '2020-11-19',","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/vod-upload.js#L98-L134","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nauth = JSON.parse(result.auth);\n// after\nlet raw = result.auth;\nif (/^STS?[0-9]/.test(raw) || /^[A-Za-z0-9+/=]+$/.test(raw)) {\n  raw = Buffer.from(raw, 'base64').toString('utf8'); // decode before parse if encoded\n}\nauth = JSON.parse(raw);","handlingStrategy":"validation","validationCode":"function looksLikeJsonAuth(s) {\n  return typeof s === 'string' && s.trim().startsWith('{');\n}\n// before relying on result.auth:\nif (!looksLikeJsonAuth(result.auth)) throw new Error('auth 字段不是 JSON 字符串');","typeGuard":"null","tryCatchPattern":"try {\n  auth = JSON.parse(result.auth);\n} catch (error) {\n  console.error('原始 auth 内容:', String(result.auth).slice(0, 200));\n  throw error; // HTML content => re-login path; encoded content => decode path\n}","preventionTips":["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."],"tags":["douyin","json-parse","upload-auth","encoding"],"backgroundTag":"json-parse-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}