jackwener/OpenCLI · error · ArgumentError
twitter search --limit must be a positive integer
Error message
twitter search --limit must be a positive integer
What it means
ArgumentError raised when the --limit value is not a positive integer. The library validates Number(kwargs.limit) is an integer > 0 before issuing the search request.
Source
Thrown at clis/twitter/search.js:285
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 = [];
const seen = new Set();
let cursor = null;
// Runaway guard only; --limit and cursor exhaustion control normal pagination.View on GitHub (pinned to 49907e53dc)
Solutions
- Pass a whole number greater than 0, e.g. --limit 15
- Remove units/decimals from the value
- Ensure the CI variable supplying the limit is set and numeric
Example fix
// before opencli twitter search opencli --limit 0 // after opencli twitter search opencli --limit 15
Defensive patterns
Strategy: validation
Validate before calling
function isValidLimit(v) { const n = Number(v); return Number.isInteger(n) && n > 0; }
if (!isValidLimit(process.env.SEARCH_LIMIT ?? kwargs.limit)) throw new Error('limit must be a positive integer'); Type guard
function isPositiveInt(v) { return Number.isInteger(Number(v)) && Number(v) > 0; } Try / catch
try {
await opencli.twitter.search(q, { limit });
} catch (e) {
if (e.name === 'ArgumentError' && /--limit/.test(e.message)) {
console.error('Use e.g. --limit 15');
} else throw e;
} Prevention
- Pass whole numbers > 0 only
- Strip units/decimals from CLI values
- Ensure CI/env variables supplying the limit are set
- Coerce and validate in your wrapper before calling
When it happens
Trigger: `--limit 0`, `--limit -5`, `--limit abc`, `--limit 12.5`, or limit passed as an empty string — anything failing Number.isInteger(Number(v)) || v <= 0.
Common situations: Typos on the command line, copying fractional defaults like '10.0', environment/CI variables expanding to empty, or passing limit as a string with units ('15 tweets').
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- eastmoney convertible --limit must be an integer between 1 a
- twitter collection --limit must be an integer between 1 and
- twitter profile username must be a valid Twitter/X handle
- Invalid --from username: ${JSON.stringify(kwargs.from)}
- twitter search query is empty
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8cf8066b29a36692.
Report an issue: GitHub.