{"record":{"id":"61ff8708c075fcea","repo":"jackwener/OpenCLI","slug":"output-file-requires-all","errorCode":null,"errorMessage":"--output-file requires --all","messagePattern":"--output-file requires --all","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/twitter/bookmarks.js","lineNumber":196,"sourceCode":"        { name: 'resume-file', type: 'string', help: 'Resume file for long-running all-pages bookmark syncs.' },\n        { name: 'output-file', type: 'string', help: 'Write all-page results to JSONL. Requires --all and --resume-file.' },\n        { name: 'max-pages', type: 'int', help: `Optional pagination safety cap (default ${DEFAULT_MAX_PAGINATION_PAGES}; raised automatically with --all).` },\n        { name: 'top-by-engagement', type: 'int', default: 0, help: 'When set to N>0, re-rank the bookmarks by weighted engagement (likes×1 + retweets×3 + replies×2 + bookmarks×5 + log10(views+1)×0.5) and return the top N. Default 0 keeps the API\\'s native (saved-time) ordering. Incompatible with --output-file.' },\n    ],\n    columns: ['id', 'author', 'text', 'likes', 'retweets', 'bookmarks', 'created_at', 'url', 'has_media', 'media_urls', 'media_posters'],\n    func: async (page, kwargs) => {\n        const fetchAll = Boolean(kwargs.all);\n        const limit = fetchAll ? Number.POSITIVE_INFINITY : (kwargs.limit || 20);\n        const resumeFile = resolveOptionalFilePath(kwargs['resume-file'], '--resume-file');\n        const outputFile = resolveOptionalFilePath(kwargs['output-file'], '--output-file');\n        const useOutputFile = Boolean(fetchAll && outputFile);\n        const maxPages = resolveMaxPages(kwargs, fetchAll);\n        const topByEngagement = Number(kwargs['top-by-engagement'] || 0);\n        if (useOutputFile && topByEngagement > 0) {\n            throw new ArgumentError('--top-by-engagement cannot be combined with --output-file');\n        }\n        if (outputFile && !fetchAll) {\n            throw new ArgumentError('--output-file requires --all');\n        }\n        if (resumeFile && !fetchAll) {\n            throw new ArgumentError('--resume-file requires --all');\n        }\n        if (outputFile && !resumeFile) {\n            throw new ArgumentError('--output-file requires --resume-file so partial archives remain resumable');\n        }\n        const cookies = await page.getCookies({ url: 'https://x.com' });\n        const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;\n        if (!ct0)\n            throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');\n        const queryId = await resolveTwitterQueryId(page, 'Bookmarks', BOOKMARKS_QUERY_ID);\n        const headers = JSON.stringify({\n            'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,\n            'X-Csrf-Token': ct0,\n            'X-Twitter-Auth-Type': 'OAuth2Session',\n            'X-Twitter-Active-User': 'yes',\n        });","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/bookmarks.js#L178-L214","documentation":"--output-file only makes sense for a full multi-page archive, which requires --all; and per the follow-up check it also requires --resume-file so partial archives remain resumable. Passing --output-file without --all throws this ArgumentError.","triggerScenarios":"Invoking `twitter bookmarks --output-file archive.jsonl` without --all (or with --all but without --resume-file, which triggers the related '--output-file requires --resume-file' error).","commonSituations":"Copying an archive example but omitting --all; typo like `--al` silently not enabling fetchAll; script template drift where --all was removed.","solutions":["Add --all (and --resume-file) when using --output-file: `--all --resume-file r.json --output-file a.jsonl`.","If you only want a small fetch, drop --output-file and rely on --limit.","Check the script for a misspelled/missing --all flag."],"exampleFix":"// before\ncli twitter bookmarks --output-file a.jsonl\n// after\ncli twitter bookmarks --all --resume-file r.json --output-file a.jsonl","handlingStrategy":"validation","validationCode":"function assertArchiveFlags(args) {\n  const has = (f) => args.includes(f);\n  if (has('--output-file')) {\n    if (!has('--all')) throw new Error('--output-file requires --all');\n    if (!has('--resume-file')) throw new Error('--output-file requires --resume-file');\n  }\n}","typeGuard":"null","tryCatchPattern":"try {\n  await run(args);\n} catch (e) {\n  if (String(e.message).includes('--output-file requires --all')) {\n    await run(['--all', '--resume-file', resumePath, '--output-file', outPath, ...args]);\n  } else throw e;\n}","preventionTips":["Always use the full archive triple: --all --resume-file --output-file.","Check for typos that silently disable boolean flags (e.g. `--al`).","Lint CLI invocations in scripts with a wrapper that validates flag combos.","Remember --output-file is only for full-page archival, not small limit-based fetches."],"tags":["argument-error","cli","missing-flag"],"backgroundTag":"missing-required-flag","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}