jackwener/OpenCLI · error · ArgumentError
douyin user-videos requires a sec_uid
Error message
douyin user-videos requires a sec_uid
What it means
An ArgumentError thrown by normalizeSecUid when the sec_uid input is empty (after trimming / nullish coercion). Douyin user-videos requires a sec_uid to build the https://www.douyin.com/user/<sec_uid> page URL, and an empty value would produce a meaningless request. The error message carries a hint explaining the expected shape.
Source
Thrown at clis/douyin/user-videos.js:18
import { cli, Strategy } from '@jackwener/opencli/registry';
import { ArgumentError, CliError, CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';
import { fetchDouyinComments, fetchDouyinUserVideos } from './_shared/public-api.js';
export const MAX_USER_VIDEOS_LIMIT = 20;
export const USER_VIDEO_COMMENT_CONCURRENCY = 4;
export const DEFAULT_COMMENT_LIMIT = 10;
// sec_uid is base64url. Anything else (a nickname, a numeric UID, a search term)
// still resolves to a Douyin page, so without this guard the scrape silently
// returns some other account's videos.
// Current Douyin sec_uid values use the stable `MS4wLjABAAAA` prefix followed
// by a long base64url payload. Requiring the prefix prevents ordinary ASCII
// nicknames and long numeric UIDs from passing a shape-only character check.
const SEC_UID_PATTERN = /^MS4wLjABAAAA[A-Za-z0-9_-]{8,}$/;
const SEC_UID_HINT = 'sec_uid looks like MS4wLjABAAAA… — it is the last path segment of https://www.douyin.com/user/<sec_uid>, not a nickname or a numeric UID.';
export function normalizeSecUid(input) {
const raw = String(input ?? '').trim();
if (!raw)
throw new ArgumentError('douyin user-videos requires a sec_uid', SEC_UID_HINT);
const fromUrl = raw.match(/douyin\.com\/user\/([A-Za-z0-9_-]+)/);
const candidate = fromUrl ? fromUrl[1] : raw;
if (!SEC_UID_PATTERN.test(candidate))
throw new ArgumentError(`"${raw}" is not a Douyin sec_uid`, SEC_UID_HINT);
return candidate;
}
export function normalizeUserVideosLimit(limit) {
const numeric = Number(limit);
if (!Number.isFinite(numeric))
return MAX_USER_VIDEOS_LIMIT;
return Math.min(MAX_USER_VIDEOS_LIMIT, Math.max(1, Math.round(numeric)));
}
export function normalizeCommentLimit(limit) {
const numeric = Number(limit);
if (!Number.isFinite(numeric))
return DEFAULT_COMMENT_LIMIT;
return Math.min(DEFAULT_COMMENT_LIMIT, Math.max(1, Math.round(numeric)));
}View on GitHub (pinned to 49907e53dc)
Solutions
- Provide the sec_uid, e.g. `douyin user-videos --sec-uid MS4wLjABAAAA...`.
- Paste the last path segment of the creator's profile URL https://www.douyin.com/user/<sec_uid>.
- In scripts, check the variable is non-empty before invoking the command.
Example fix
// before
await run(['douyin', 'user-videos', '--sec-uid', process.env.DY_SEC_UID]);
// after
if (!process.env.DY_SEC_UID) throw new Error('DY_SEC_UID is not set');
await run(['douyin', 'user-videos', '--sec-uid', process.env.DY_SEC_UID]); Defensive patterns
Strategy: validation
Validate before calling
const secUid = (input ?? '').trim();
if (!secUid) throw new Error('sec_uid is required: last path segment of https://www.douyin.com/user/<sec_uid>'); Type guard
function hasSecUid(v) {
return typeof v === 'string' && v.trim().length > 0;
} Try / catch
try {
await run('douyin user-videos', { sec_uid });
} catch (e) {
if (e.name === 'ArgumentError' && /requires a sec_uid/.test(e.message)) {
console.error('Set --sec-uid from the profile URL');
process.exitCode = 2;
return;
}
throw e;
} Prevention
- Read sec_uid from a checked config value, not an unguarded env var.
- Fail fast in your own code when the value is empty before shelling out.
When it happens
Trigger: Calling `douyin user-videos` (or secUid resolution path) with an empty --sec-uid flag, undefined/undefined-config value, or a value that is only whitespace.
Common situations: Config/env variable for the sec_uid not set; a shell variable expanding to empty; passing a profile URL that failed to parse earlier and yielded an empty string downstream.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- 视频文件不存在: ${videoPath}
- 必须提供 --reschedule 或 --caption
- ${raw} is not a Douyin sec_uid
- douyin videos limit must be an integer between ${MIN_LIMIT}
- Argument "media" is required.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/528dc1d844f4aa8c.
Report an issue: GitHub.