jackwener/OpenCLI · error · ArgumentError
--output-file requires --resume-file so partial archives rem
Error message
--output-file requires --resume-file so partial archives remain resumable
What it means
When --output-file is given, the run can be interrupted mid-archive; without a --resume-file the partial on-disk archive has no state to resume from and would be useless. The CLI therefore requires --resume-file alongside --output-file and throws ArgumentError otherwise.
Source
Thrown at clis/twitter/likes.js:221
func: async (page, kwargs) => {
const fetchAll = Boolean(kwargs.all);
const limit = fetchAll ? Number.POSITIVE_INFINITY : (kwargs.limit || 20);
const resumeFile = resolveOptionalFilePath(kwargs['resume-file'], '--resume-file');
const outputFile = resolveOptionalFilePath(kwargs['output-file'], '--output-file');
const useOutputFile = Boolean(fetchAll && outputFile);
const maxPages = resolveMaxPages(kwargs, fetchAll);
const topByEngagement = Number(kwargs['top-by-engagement'] || 0);
if (useOutputFile && topByEngagement > 0) {
throw new ArgumentError('--top-by-engagement cannot be combined with --output-file');
}
if (outputFile && !fetchAll) {
throw new ArgumentError('--output-file requires --all');
}
if (resumeFile && !fetchAll) {
throw new ArgumentError('--resume-file requires --all');
}
if (outputFile && !resumeFile) {
throw new ArgumentError('--output-file requires --resume-file so partial archives remain resumable');
}
const rawUsername = String(kwargs.username ?? '').trim();
let username = normalizeTwitterScreenName(rawUsername);
if (rawUsername && !username) {
throw new ArgumentError('twitter likes username must be a valid Twitter/X handle', 'Example: opencli twitter likes @jack --limit 20');
}
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)');
// If no username provided, detect the logged-in user.
// Bridge wraps primitive page.evaluate returns as { session, data:<value> };
// unwrap so the href string is usable downstream.
if (!username) {
// Force a navigation to the home surface so the AppTabBar sidebar
// is rendered; the framework pre-nav lands on bare x.com which
// does not always expose AppTabBar_Profile_Link.
await page.goto('https://x.com/home');View on GitHub (pinned to 49907e53dc)
Solutions
- Add --resume-file pointing to a JSON path (new or from a prior interrupted run) when using --output-file.
- Remove --output-file if you don't need a disk archive and accept in-memory results.
Example fix
// before opencli twitter likes @jack --all --output-file likes.ndjson // after opencli twitter likes @jack --all --output-file likes.ndjson --resume-file likes-resume.json
Defensive patterns
Strategy: validation
Validate before calling
if (args.includes('--output-file') && !args.includes('--resume-file')) {
throw new Error('--output-file requires --resume-file');
} Prevention
- Always pass --output-file and --resume-file together as a pair.
- Point both at the same working directory so partial archives remain resumable.
When it happens
Trigger: Running `opencli twitter likes @jack --all --output-file likes.ndjson` without --resume-file.
Common situations: User reads docs showing --output-file alone; older scripts written before the resumability requirement was added; simplifying a command line by dropping the 'extra' resume flag.
Related errors
- --resume-file requires --all
- twitter download requires either <username> or --tweet-url
- Use either <username> or --tweet-url, not both
- twitter download username must be a valid Twitter/X handle
- Twitter likes resume file ${filePath} count does not match i
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/20c6e813cab7f0f4.
Report an issue: GitHub.