{"record":{"id":"0b479156f003fda6","repo":"jackwener/OpenCLI","slug":"message","errorCode":null,"errorMessage":"获取抖音上传授权失败: ${message}","messagePattern":"获取抖音上传授权失败: (.+?)","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/vod-upload.js","lineNumber":105,"sourceCode":"    if (typeof condition === 'string') {\n      const parsedCondition = JSON.parse(condition);\n      return parsedCondition.UserId || '';\n    }\n  } catch {\n    return '';\n  }\n  return '';\n}\n\nexport async function getUploadAuthV5Credentials(page) {\n  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,","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/vod-upload.js#L87-L123","documentation":"getUploadAuthV5Credentials fetches temporary VOD upload credentials via an in-page fetch on creator.douyin.com. When the endpoint returns status_code 401/403, or the message matches auth/login/captcha-related keywords, the code rethrows as AuthRequiredError so callers can prompt a re-login. This means the browser session cookies for creator.douyin.com are no longer valid or are being challenged.","triggerScenarios":"The AUTH_V5_URL response has status_code 401 or 403, or its status_msg/message matches /login|cookie|auth|captcha|verify|forbidden|permission|登录|登陆|权限|验证|验证码/i.","commonSituations":"Session cookies expired after hours/days; the account was logged out remotely; Douyin served a CAPTCHA or risk-control verification; the account lacks upload permission; IP risk control triggers a verify challenge.","solutions":["Log in (or re-log in) to creator.douyin.com in the same browser/profile the automation drives, then retry.","If a CAPTCHA/verification challenge was raised, complete it manually in the browser before retrying.","Confirm the account actually has video-upload permission for the VOD space.","Clear stale cookies or use a fresh logged-in profile if repeated 403s persist.","Check whether requests come from a risky IP (VPN/proxy) and switch networks."],"exampleFix":"// before\nconst creds = await getUploadAuthV5Credentials(page);\n// after\ntry {\n  const creds = await getUploadAuthV5Credentials(page);\n} catch (e) {\n  if (e instanceof AuthRequiredError) {\n    await promptUserLogin('creator.douyin.com'); // re-login then retry\n    return getUploadAuthV5Credentials(page);\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// pre-check login state in page context before fetching auth\nconst loggedIn = await page.evaluate(() => document.cookie.includes('sessionid'));\nif (!loggedIn) throw new Error('请先登录 creator.douyin.com 再上传');","typeGuard":"function isAuthRequiredError(e) {\n  return e instanceof Error && e.name === 'AuthRequiredError';\n}","tryCatchPattern":"try {\n  const creds = await getUploadAuthV5Credentials(page);\n} catch (e) {\n  if (isAuthRequiredError(e)) {\n    await promptLogin('creator.douyin.com');\n    return getUploadAuthV5Credentials(page);\n  }\n  throw e;\n}","preventionTips":["Keep the automated browser profile logged in and refresh the session before long upload batches.","Detect CAPTCHA/verification pages proactively before starting uploads.","Run from a stable residential IP; avoid datacenter proxies that trigger risk control.","Confirm account upload permissions before automating."],"tags":["auth","session-expired","douyin","login-required"],"backgroundTag":"auth-required-session-expired","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}