jackwener/OpenCLI · error · ArgumentError
twitter search query is empty
Error message
twitter search query is empty
What it means
ArgumentError thrown by the search command when the final assembled query string is empty — i.e. the positional <query> was empty AND no --from/--has/--exclude options contributed any terms. X's search endpoint requires a non-empty query, so the library fails fast.
Source
Thrown at clis/twitter/search.js:282
description: 'Search Twitter/X for tweets, with optional --from / --has / --exclude / --product filters mapped to X\'s search operators',
domain: 'x.com',
strategy: Strategy.COOKIE,
browser: true,
args: [
{ name: 'query', type: 'string', required: true, positional: true, help: 'Search query. Raw X operators (e.g. "exact phrase", #tag, OR, lang:en, since:YYYY-MM-DD, from:, since:) are passed through unchanged.' },
{ name: 'filter', type: 'string', default: 'top', choices: ['top', 'live'], help: 'Legacy alias for --product. Kept for backwards compatibility; if --product is set it wins.' },
{ name: 'product', type: 'string', choices: PRODUCT_CHOICES, help: 'Which X search tab to read: top (default), live (Latest), photos, videos. Maps to the f= URL param.' },
{ name: 'from', type: 'string', help: 'Restrict to tweets authored by <user>. Leading @ is stripped. Equivalent to appending `from:<user>` to the query.' },
{ name: 'has', type: 'string', choices: HAS_CHOICES, help: 'Restrict to tweets that have media|images|videos|links|replies. Maps to X\'s `filter:<has>` operator.' },
{ name: 'exclude', type: 'string', choices: EXCLUDE_CHOICES, help: 'Exclude tweets matching <type>: replies|retweets|media|links. Maps to X\'s `-filter:<x>` operator (retweets → -filter:nativeretweets).' },
{ name: 'limit', type: 'int', default: 15, help: 'Maximum number of tweets to return (default 15). Result count after server-side filtering.' },
{ name: 'top-by-engagement', type: 'int', default: 0, help: 'When set to N>0, re-rank the results by weighted engagement (likes×1 + retweets×3 + replies×2 + bookmarks×5 + log10(views+1)×0.5) and return the top N. Default 0 keeps X\'s native ordering.' },
],
columns: ['id', 'author', 'bio', 'text', 'created_at', 'likes', 'views', 'url', 'has_media', 'media_urls', 'media_posters', 'card', 'quoted_tweet'],
func: async (page, kwargs) => {
const finalQuery = buildSearchQuery(kwargs.query, kwargs);
if (!finalQuery) {
throw new ArgumentError('twitter search query is empty', 'Provide a non-empty <query>, or use at least one of --from / --has / --exclude.');
}
if (!Number.isInteger(Number(kwargs.limit)) || Number(kwargs.limit) <= 0) {
throw new ArgumentError('twitter search --limit must be a positive integer', 'Example: opencli twitter search opencli --limit 15');
}
const cookies = await page.getCookies({ url: 'https://x.com' });
const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;
if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');
await page.goto('https://x.com/home', { waitUntil: 'load', settleMs: 1000 });
const operation = await resolveTwitterOperationMetadata(page, 'SearchTimeline', SEARCH_TIMELINE_OPERATION);
const headers = JSON.stringify({
'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
'X-Csrf-Token': ct0,
'X-Twitter-Auth-Type': 'OAuth2Session',
'X-Twitter-Active-User': 'yes',
'Content-Type': 'application/json',
});
const product = resolveSearchProduct(kwargs);
const results = [];View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a non-empty positional <query>
- Or supply at least one filter: --from, --has, or --exclude
- Check shell quoting/variable expansion so the query is not stripped to an empty string
Example fix
// before opencli twitter search '' // after opencli twitter search 'opencli' --limit 15 // or flag-only search: opencli twitter search '' --from jack # if supported spelling of flags is used
Defensive patterns
Strategy: validation
Validate before calling
function hasSearchInput(kwargs) {
return Boolean(String(kwargs.query ?? '').trim() || kwargs.from || kwargs.has || kwargs.exclude);
}
if (!hasSearchInput(kwargs)) throw new Error('Provide a query or --from/--has/--exclude'); Type guard
function isNonEmptyString(v) { return typeof v === 'string' && v.trim().length > 0; } Try / catch
try {
await opencli.twitter.search(query);
} catch (e) {
if (e.name === 'ArgumentError' && /empty/.test(e.message)) {
console.error('Query was empty; supply <query> or filter flags');
} else throw e;
} Prevention
- Always pass a non-empty positional query
- Check flag spelling (--from, --has, --exclude) when doing flag-only searches
- Guard against empty shell/CI variables before interpolation
- Trim and validate user input before invoking
When it happens
Trigger: `opencli twitter search ''`, calling search programmatically with kwargs.query = null/undefined and no filter flags, or quoting issues so the shell passes an empty string as the query.
Common situations: Script variables that expand to empty strings, forgetting the positional query while intending a --from-only search but misspelling the flag name, or piping empty input.
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
- Invalid --from username: ${JSON.stringify(kwargs.from)}
- twitter tweet URL cannot be empty
- ${label} cannot be empty
- ${label} cannot be empty
- keyword cannot be empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ddd19bea3a8635da.
Report an issue: GitHub.