jackwener/OpenCLI · error · CommandExecutionError

Douyin user info response is missing user_info

Error message

Douyin user info response is missing user_info

What it means

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.

Source

Thrown at clis/douyin/auth.js:17

import { AuthRequiredError, CommandExecutionError } from '@jackwener/opencli/errors';
import { registerSiteAuthCommands } from '../_shared/site-auth.js';
import { browserFetch } from './_shared/browser-fetch.js';

async function hasDouyinSessionCookies(page) {
  const cookies = await page.getCookies({ url: 'https://creator.douyin.com' });
  const names = new Set(cookies.map(cookie => cookie.name));
  return names.has('sessionid') || names.has('uid_tt') || names.has('passport_csrf_token');
}

async function verifyDouyinIdentity(page) {
  await page.goto('https://creator.douyin.com');
  const url = 'https://creator.douyin.com/web/api/media/user/info/?aid=1128';
  const payload = await browserFetch(page, 'GET', url);
  const user = payload.user_info ?? payload.user;
  if (!user) {
    throw new CommandExecutionError('Douyin user info response is missing user_info');
  }
  return {
    id: user.uid ?? '',
    username: user.nickname ?? '',
    followers: user.follower_count ?? 0,
  };
}

registerSiteAuthCommands({
  site: 'douyin',
  domain: 'creator.douyin.com',
  loginUrl: 'https://creator.douyin.com/',
  columns: ['id', 'username', 'followers'],
  quickCheck: hasDouyinSessionCookies,
  verify: verifyDouyinIdentity,
  poll: async (page) => {
    if (!await hasDouyinSessionCookies(page)) {
      throw new AuthRequiredError('creator.douyin.com', 'Waiting for Douyin creator session cookies');

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Run the site auth login flow to (re)establish session cookies, then retry
  2. Check the payload returned by user/info (log it) to see if the shape changed under data/error wrappers
  3. Confirm cookies sessionid/uid_tt/passport_csrf_token exist for creator.douyin.com
  4. Update verifyDouyinIdentity to read the new payload path if Douyin renamed the field

Example fix

// before
const user = payload.user_info ?? payload.user;
// after
const user = payload.user_info ?? payload.user ?? payload.data?.user_info;
if (!user) throw new CommandExecutionError('missing user_info: ' + JSON.stringify(payload).slice(0, 300));
Defensive patterns

Strategy: validation

Validate before calling

// before calling verify, ensure session cookies exist
const cookies = await page.getCookies({ url: 'https://creator.douyin.com' });
const names = new Set(cookies.map(c => c.name));
if (!names.has('sessionid') && !names.has('uid_tt')) throw new Error('Douyin session missing — login first');

Type guard

function hasUserInfo(payload) {
  return Boolean(payload && (payload.user_info ?? payload.user));
}

Try / catch

try {
  const identity = await verifyDouyinIdentity(page);
} catch (e) {
  if (/missing user_info/.test(e.message)) {
    await runLoginFlow(page); // re-auth then retry once
    return verifyDouyinIdentity(page);
  } throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/b1b3cc5d012e6daa. Report an issue: GitHub.