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 archiving to a JSONL output file, a matching --resume-file is mandatory so a partially written archive can be continued. clis/twitter/bookmarks.js:202 throws ArgumentError when --output-file is given without --resume-file. Without resume state, an interrupted run would leave an unresumable partial archive.

Source

Thrown at clis/twitter/bookmarks.js:202

    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 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)');
        const queryId = await resolveTwitterQueryId(page, 'Bookmarks', BOOKMARKS_QUERY_ID);
        const headers = JSON.stringify({
            'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,
            'X-Csrf-Token': ct0,
            'X-Twitter-Auth-Type': 'OAuth2Session',
            'X-Twitter-Active-User': 'yes',
        });
        const resumed = fetchAll ? readResumeFile(resumeFile, {
            source: 'bookmarks',
            outputFile: useOutputFile ? outputFile : null,
        }) : null;
        if (useOutputFile && resumed && resumed.count > 0 && !fs.existsSync(outputFile)) {
            throw new CommandExecutionError(`Twitter bookmarks output file is missing for resume state: ${outputFile}`);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Add --resume-file pointing to the state file (e.g. archive.resume.json) alongside --output-file.
  2. Remove --output-file if you want an in-memory fetch that tolerates interruption via the resume file alone.
  3. Wrap both flags in a single script/alias so they are never separated.

Example fix

// before
twitter bookmarks --all --output-file bookmarks.jsonl
// after
twitter bookmarks --all --output-file bookmarks.jsonl --resume-file bookmarks.resume.json
Defensive patterns

Strategy: validation

Validate before calling

if (has('--output-file') && !has('--resume-file')) {
  throw new Error('--output-file requires --resume-file so partial archives remain resumable');
}

Type guard

function canArchiveToOutput(opts) {
  return typeof opts.outputFile === 'string' && typeof opts.resumeFile === 'string';
}

Try / catch

try {
  await runBookmarks(argv);
} catch (e) {
  if (e instanceof ArgumentError && e.message.includes('requires --resume-file')) {
    console.error('Add --resume-file <state.json> alongside --output-file.');
    process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Running `twitter bookmarks --all --output-file archive.jsonl` without `--resume-file`. Pure flag check in the argument validation block, before cookies/network access.

Common situations: Users adding --output-file to an existing command line but omitting --resume-file; automations that build flags conditionally and skip the resume flag; misunderstanding that output-file alone is sufficient for archiving.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/89c26de97ae53fc7. Report an issue: GitHub.