{"record":{"id":"b1b3cc5d012e6daa","repo":"jackwener/OpenCLI","slug":"douyin-user-info-response-is-missing-user-info","errorCode":null,"errorMessage":"Douyin user info response is missing user_info","messagePattern":"Douyin user info response is missing user_info","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/auth.js","lineNumber":17,"sourceCode":"import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';\nimport { registerSiteAuthCommands } from '../_shared/site-auth.js';\nimport { browserFetch } from './_shared/browser-fetch.js';\n\nasync function hasDouyinSessionCookies(page) {\n  const cookies = await page.getCookies({ url: 'https://creator.douyin.com' });\n  const names = new Set(cookies.map(cookie => cookie.name));\n  return names.has('sessionid') || names.has('uid_tt') || names.has('passport_csrf_token');\n}\n\nasync function verifyDouyinIdentity(page) {\n  await page.goto('https://creator.douyin.com');\n  const url = 'https://creator.douyin.com/web/api/media/user/info/?aid=1128';\n  const payload = await browserFetch(page, 'GET', url);\n  const user = payload.user_info ?? payload.user;\n  if (!user) {\n    throw new CommandExecutionError('Douyin user info response is missing user_info');\n  }\n  return {\n    id: user.uid ?? '',\n    username: user.nickname ?? '',\n    followers: user.follower_count ?? 0,\n  };\n}\n\nregisterSiteAuthCommands({\n  site: 'douyin',\n  domain: 'creator.douyin.com',\n  loginUrl: 'https://creator.douyin.com/',\n  columns: ['id', 'username', 'followers'],\n  quickCheck: hasDouyinSessionCookies,\n  verify: verifyDouyinIdentity,\n  poll: async (page) => {\n    if (!await hasDouyinSessionCookies(page)) {\n      throw new AuthRequiredError('creator.douyin.com', 'Waiting for Douyin creator session cookies');","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/auth.js#L1-L35","documentation":"Thrown by verifyDouyinIdentity when the creator.douyin.com user/info API returns a payload lacking both user_info and user fields. The library uses this response to confirm the logged-in Douyin creator identity, so a missing user object means the session is not authenticated or the API shape changed. Thrown as a CommandExecutionError to abort auth verification.","triggerScenarios":"Running verify before QR login completes (no valid session cookies); session cookies expired so the API returns an anonymous/error payload; creator.douyin.com renames user_info (e.g. wraps in data or error envelope); browserFetch intercepted a redirect to a login page.","commonSituations":"Re-running `douyin auth whoami` days after login when sessionid expired; rate limiting or risk-control intercepting the request; scraping with a fresh browser profile that never logged in.","solutions":["Run the site auth login flow to (re)establish session cookies, then retry","Check the payload returned by user/info (log it) to see if the shape changed under data/error wrappers","Confirm cookies sessionid/uid_tt/passport_csrf_token exist for creator.douyin.com","Update verifyDouyinIdentity to read the new payload path if Douyin renamed the field"],"exampleFix":"// before\nconst user = payload.user_info ?? payload.user;\n// after\nconst user = payload.user_info ?? payload.user ?? payload.data?.user_info;\nif (!user) throw new CommandExecutionError('missing user_info: ' + JSON.stringify(payload).slice(0, 300));","handlingStrategy":"validation","validationCode":"// before calling verify, ensure session cookies exist\nconst cookies = await page.getCookies({ url: 'https://creator.douyin.com' });\nconst names = new Set(cookies.map(c => c.name));\nif (!names.has('sessionid') && !names.has('uid_tt')) throw new Error('Douyin session missing — login first');","typeGuard":"function hasUserInfo(payload) {\n  return Boolean(payload && (payload.user_info ?? payload.user));\n}","tryCatchPattern":"try {\n  const identity = await verifyDouyinIdentity(page);\n} catch (e) {\n  if (/missing user_info/.test(e.message)) {\n    await runLoginFlow(page); // re-auth then retry once\n    return verifyDouyinIdentity(page);\n  } throw e;\n}","preventionTips":["Run the login flow before any verify/whoami call","Check sessionid cookie presence before hitting user/info","Log unexpected payloads to catch Douyin response-shape renames early","Re-login periodically; creator.douyin.com sessions expire"],"tags":["douyin","auth","session","api-error"],"backgroundTag":"unauthenticated-session-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}