jackwener/OpenCLI · warning · ArgumentError
twitter download requires either <username> or --tweet-url
Error message
twitter download requires either <username> or --tweet-url
What it means
The twitter download CLI requires exactly one input selector: a positional <username> to scan a profile's media, or --tweet-url for a single tweet. This ArgumentError is thrown before any network work when neither argument is provided (and a sibling error fires when both are). It is an ordinary usage/validation error, not a runtime failure.
Source
Thrown at clis/twitter/download.js:323
access: 'read',
description: 'Download Twitter/X media (images and videos). Provide either <username> to fetch every media item from their profile via the GraphQL UserMedia endpoint with cursor pagination, or --tweet-url to download a single tweet.',
domain: 'x.com',
strategy: Strategy.COOKIE,
browser: true,
args: [
{ name: 'username', positional: true, help: 'Twitter username (with or without @) to scan their profile media. Either <username> or --tweet-url is required.' },
{ name: 'tweet-url', help: 'Single tweet URL to download. Use this OR <username>, not both required at once.' },
{ name: 'limit', type: 'int', default: 10, help: 'Maximum number of media items to download when scanning a profile (default 10). Ignored when --tweet-url is used.' },
{ name: 'output', default: './twitter-downloads', help: 'Output directory (default ./twitter-downloads). A per-source subdir is created inside.' },
],
columns: ['index', 'tweet_id', 'url', 'type', 'status', 'size'],
func: async (page, kwargs) => {
try {
const rawUsername = String(kwargs.username ?? '').trim();
const tweetUrl = String(kwargs['tweet-url'] ?? '').trim();
const output = kwargs.output;
if (!rawUsername && !tweetUrl) {
throw new ArgumentError('twitter download requires either <username> or --tweet-url');
}
if (rawUsername && tweetUrl) {
throw new ArgumentError('Use either <username> or --tweet-url, not both');
}
if (tweetUrl) {
return downloadSingleTweet(page, tweetUrl, output);
}
const limit = requireLimit(kwargs.limit);
const username = normalizeTwitterScreenName(rawUsername);
if (!username) {
throw new ArgumentError('twitter download username must be a valid Twitter/X handle', 'Example: opencli twitter download @jack --limit 20');
}
return downloadUserMedia(page, username, limit, output);
}
catch (err) {
if (err instanceof CliError) throw err;
throw new CommandExecutionError(`twitter download failed: ${err?.message ?? String(err)}`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a username positionally: opencli twitter download @handle --limit 20
- Or pass a single tweet: opencli twitter download --tweet-url https://x.com/user/status/1234567890
- Provide exactly one of the two — not both, or the sibling 'Use either <username> or --tweet-url, not both' error fires.
- Check your shell/CI quoting so the positional username is actually passed through to the CLI.
Example fix
// before await opencli twitter download --limit 10 // ArgumentError: twitter download requires either <username> or --tweet-url // after await opencli twitter download @jack --limit 10
Defensive patterns
Strategy: validation
Validate before calling
const rawUsername = String(kwargs.username ?? '').trim();
const tweetUrl = String(kwargs['tweet-url'] ?? '').trim();
if (!rawUsername && !tweetUrl) {
throw new ArgumentError('twitter download requires either <username> or --tweet-url');
}
if (rawUsername && tweetUrl) {
throw new ArgumentError('Use either <username> or --tweet-url, not both');
} Type guard
function hasValidInput(args) {
const u = String(args?.username ?? '').trim();
const t = String(args?.['tweet-url'] ?? '').trim();
return Boolean(u) !== Boolean(t); // exactly one present
} Try / catch
try {
await twitterDownload(...args);
} catch (err) {
if (err instanceof ArgumentError && err.message.includes('requires either')) {
console.error('Usage: opencli twitter download <username> | --tweet-url <url>');
process.exitCode = 2;
} else throw err;
} Prevention
- Always pass exactly one of: positional username or --tweet-url
- Check shell quoting so the positional username reaches the CLI
- Use the flag name '--tweet-url' exactly (not --url)
- Add the input check to CI/scripts before invoking the CLI
When it happens
Trigger: Calling 'twitter download' with no positional username and no --tweet-url flag (e.g. passing only --limit or --output).
Common situations: Scripting the CLI and forgetting the positional argument; quoting/argument-passing bugs where the username is swallowed by the shell; mistaking --tweet-url's flag name (using --url or a positional tweet URL instead); CI configs missing required parameters.
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
- 未知的 action: ${action}
- --resume-file requires --all
- Use either <username> or --tweet-url, not both
- twitter download username must be a valid Twitter/X handle
- --top-by-engagement cannot be combined with --output-file
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4405b7077293a78b.
Report an issue: GitHub.