{"record":{"id":"9b431bf0994b909e","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-twitter-follow","errorCode":null,"errorMessage":"Browser session required for twitter follow","messagePattern":"Browser session required for twitter follow","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/follow.js","lineNumber":17,"sourceCode":"import { CommandExecutionError, TimeoutError } from '@jackwener/opencli/errors';\nimport { cli, Strategy } from '@jackwener/opencli/registry';\ncli({\n    site: 'twitter',\n    name: 'follow',\n    access: 'write',\n    description: 'Follow a Twitter user',\n    domain: 'x.com',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [\n        { name: 'username', type: 'string', positional: true, required: true, help: 'Twitter screen name (without @)' },\n    ],\n    columns: ['status', 'message'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for twitter follow');\n        const username = kwargs.username.replace(/^@/, '');\n        await page.goto(`https://x.com/${username}`);\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const result = await page.evaluate(`(async () => {\n        let writeStarted = false;\n        try {\n            let attempts = 0;\n            let followBtn = null;\n            let unfollowTestId = null;\n\n            while (attempts < 20) {\n                // Check if already following (button shows screen_name-unfollow)\n                unfollowTestId = document.querySelector('[data-testid$=\"-unfollow\"]');\n                if (unfollowTestId) {\n                    return { ok: true, message: 'Already following @${username}.' };\n                }\n\n                // Look for the Follow button","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/follow.js#L1-L35","documentation":"The single `twitter follow` command navigates a live Page to x.com/<username> and evaluates in-page scripts, so it throws CommandExecutionError if no browser Page session was supplied (page is falsy). Nothing can be attempted without an attached browser.","triggerScenarios":"Running `opencli twitter follow <username>` with no browser daemon/extension connected; calling the command's func directly with page = null/undefined; the browser connection was lost before func executed.","commonSituations":"Scripting against the module API without establishing a session first; running before starting the managed Chrome instance; the daemon crashed between commands leaving no active session.","solutions":["Establish the browser session (start the daemon / connect Chrome) before running `twitter follow`.","Add an existence check on the page in wrapper scripts before invoking the command.","If sessions drop between commands, reconnect and batch follow operations within one session."],"exampleFix":"// before\nopencli twitter follow alice   # browser not started\n// after\nopencli connect   # start/connect the managed browser first\nopencli twitter follow alice","handlingStrategy":"try-catch","validationCode":"// Verify a usable page exists before calling single follow\nfunction requirePageForFollow(page) {\n  if (!page || typeof page.goto !== 'function' || typeof page.evaluate !== 'function') {\n    throw new Error('Browser session required for twitter follow: connect the browser first');\n  }\n}","typeGuard":"function isUsablePage(p) {\n  return p !== null && p !== undefined && typeof p.goto === 'function' && typeof p.wait === 'function' && typeof p.evaluate === 'function';\n}","tryCatchPattern":"try {\n  await follow(username);\n} catch (e) {\n  if (e.code === 'COMMAND_EXEC' && e.message.includes('Browser session required')) {\n    await connectBrowser();\n    return retry(follow, username);\n  }\n  throw e;\n}","preventionTips":["Establish the browser session before the first browser-backed command in a script.","Health-check the daemon/extension connection after long idle periods.","Batch follow operations into one session to reduce reconnect windows.","Wrap session acquisition and command execution in the same setup/teardown flow."],"tags":["browser-session","twitter","command-execution","setup"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}