{"record":{"id":"d12cf5ff63b4ccb2","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-twitter-post","errorCode":null,"errorMessage":"Browser session required for twitter post","messagePattern":"Browser session required for twitter post","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/post.js","lineNumber":306,"sourceCode":"    return result;\n}\n\ncli({\n    site: 'twitter',\n    name: 'post',\n    access: 'write',\n    description: 'Post a new tweet/thread',\n    domain: 'x.com',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [\n        { name: 'text', type: 'string', required: true, positional: true, help: 'The text content of the tweet' },\n        { name: 'images', type: 'string', required: false, help: 'Image paths, comma-separated, max 4 (jpg/png/gif/webp)' },\n    ],\n    columns: ['status', 'message', 'text', 'id', 'url'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for twitter post');\n\n        // Validate images upfront before any browser interaction.\n        const absPaths = kwargs.images ? validateImagePaths(String(kwargs.images)) : [];\n        const text = String(kwargs.text ?? '');\n\n        // The current X standalone composer is /compose/post. It keeps a single,\n        // visible composer and is the same route used by the reply command.\n        await page.goto(COMPOSE_URL, { waitUntil: 'load', settleMs: 2500 });\n        await page.wait({ selector: '[data-testid=\"tweetTextarea_0\"]', timeout: 15 });\n\n        // Attach media before inserting text. Uploading media after Draft.js has\n        // text can re-render/reset the editor, causing image-only posts.\n        if (absPaths.length > 0) {\n            await page.wait({ selector: FILE_INPUT_SELECTOR, timeout: 20 });\n            if (page.setFileInput) {\n                try {\n                    await page.setFileInput(absPaths, FILE_INPUT_SELECTOR);\n                } catch (err) {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/post.js#L288-L324","documentation":"The twitter post command's func requires an active browser page object; if `page` is falsy (no browser session was started before invoking the CLI), it throws this CommandExecutionError immediately, before any browser interaction. The library cannot post a tweet without a live browser session, so it fails fast with this explicit message.","triggerScenarios":"Calling the `twitter post` command without first launching/connecting the browser session (e.g. skipping the browser-open/start command, or invoking the CLI's func directly with page = null/undefined).","commonSituations":"Running the post command in a fresh CLI process without opening the browser first; automation scripts calling the command's func out of order; a crashed or closed browser leaving the session handle null; forgetting the session flag/URL in a batch runner.","solutions":["Start/connect the browser session (the CLI's browser open/start command) before running `twitter post`","Reopen the session if the browser crashed or was closed mid-run, then retry the post","In scripted use, assert the page handle exists before invoking the command func"],"exampleFix":"// before\nawait cli.run('twitter post', { text: 'hello' });\n// after: ensure a session exists first\nconst page = await cli.run('browser open', { url: 'https://x.com' });\nif (!page) throw new Error('browser session unavailable');\nawait cli.run('twitter post', { text: 'hello' });","handlingStrategy":"validation","validationCode":"if (!page) throw new Error('Open a browser session (browser open/start) before running twitter post');","typeGuard":"function hasBrowserSession(page) { return page != null && typeof page.evaluate === 'function' && !page.isClosed?.(); }","tryCatchPattern":"try {\n  await cli.run('twitter post', { text });\n} catch (e) {\n  if (String(e.message).includes('Browser session required')) { await cli.run('browser open', { url: 'https://x.com' }); return cli.run('twitter post', { text }); }\n  throw e;\n}","preventionTips":["Always open/start the browser session before any twitter post command","Check that the browser process hasn't crashed or been closed mid-run","In batch scripts, verify the page handle before invoking command funcs"],"tags":["browser-automation","session-required","x-twitter"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}