{"record":{"id":"83980dcc1dff9351","repo":"jackwener/OpenCLI","slug":"use-either-image-or-image-url-not-both-83980d","errorCode":null,"errorMessage":"Use either --image or --image-url, not both.","messagePattern":"Use either --image or --image-url, not both\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/reply.js","lineNumber":265,"sourceCode":"    site: 'twitter',\n    name: 'reply',\n    access: 'write',\n    description: 'Reply to a specific tweet, optionally with a local or remote image',\n    domain: 'x.com',\n    strategy: Strategy.UI, // Uses the UI directly to input and click post\n    browser: true,\n    args: [\n        { name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the tweet to reply to' },\n        { name: 'text', type: 'string', required: true, positional: true, help: 'The text content of your reply' },\n        { name: 'image', help: 'Optional local image path to attach to the reply' },\n        { name: 'image-url', help: 'Optional remote image URL to download and attach to the reply' },\n    ],\n    columns: ['status', 'message', 'text', 'url'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for twitter reply');\n        if (kwargs.image && kwargs['image-url']) {\n            throw new CommandExecutionError('Use either --image or --image-url, not both.');\n        }\n        let localImagePath;\n        let cleanupDir;\n        try {\n            if (kwargs.image) {\n                localImagePath = resolveImagePath(kwargs.image);\n            } else if (kwargs['image-url']) {\n                const downloaded = await downloadRemoteImage(kwargs['image-url']);\n                localImagePath = downloaded.absPath;\n                cleanupDir = downloaded.cleanupDir;\n            }\n            // Dedicated composer is normally more reliable than the inline\n            // tweet page reply box, but X occasionally leaves that route on the\n            // Home timeline behind a loading dialog. openReplyComposer falls\n            // back to the target tweet's visible Reply action.\n            const composer = await openReplyComposer(page, kwargs.url);\n            if (!composer?.ok) {\n                throw new CommandExecutionError(composer?.message ?? 'Could not open the reply composer.', 'Open the tweet in the browser and check whether the reply box is available.');","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/reply.js#L247-L283","documentation":"The reply command accepts an image either as a local path (--image) or as a remote URL (--image-url), but not both at once. Supplying both is ambiguous (which one gets attached?), so the command fails fast with this CommandExecutionError before any navigation or posting.","triggerScenarios":"Calling `twitter reply --image ./pic.png --image-url https://example.com/pic.png` — both truthy kwargs trigger the check at clis/twitter/reply.js:265.","commonSituations":"Script templates where both flags were filled in by defaults; copy-pasting an example command and leaving both image flags; a config file injecting --image-url on top of a manually passed --image.","solutions":["Remove one of the two flags — keep --image for local files or --image-url for remote URLs.","If the remote image is wanted, download it first and pass only --image, or vice versa.","Check wrapper scripts/config for a default --image-url that collides with a manual --image."],"exampleFix":"// before\nopencli twitter reply --url <tweet> --text \"hi\" --image ./pic.png --image-url https://x.com/pic.png\n// after\nopencli twitter reply --url <tweet> --text \"hi\" --image ./pic.png","handlingStrategy":"validation","validationCode":"if (opts.image && opts.imageUrl) {\n  throw new Error('Pass either --image or --image-url, not both');\n}","typeGuard":"null","tryCatchPattern":"try {\n  await cli('twitter', 'reply', { url, text, image });\n} catch (e) {\n  if (String(e.message).includes('Use either --image or --image-url')) {\n    // drop the conflicting flag and retry with one image source\n  } else throw e;\n}","preventionTips":["Centralize image options in one helper that picks a single source.","Audit wrapper scripts/config files for a default --image-url that collides with --image.","Document the exclusivity in your command templates."],"tags":["argument-conflict","cli-usage","twitter"],"backgroundTag":"mutually-exclusive-arguments","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}