{"record":{"id":"50b52aeb59402bce","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-twitter-unretweet","errorCode":null,"errorMessage":"Browser session required for twitter unretweet","messagePattern":"Browser session required for twitter unretweet","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/unretweet.js","lineNumber":19,"sourceCode":"import { CommandExecutionError, TimeoutError } from '@jackwener/opencli/errors';\nimport { cli, Strategy } from '@jackwener/opencli/registry';\nimport { parseTweetUrl, buildTwitterArticleScopeSource } from './shared.js';\n\ncli({\n    site: 'twitter',\n    name: 'unretweet',\n    access: 'write',\n    description: 'Undo a retweet on a specific tweet',\n    domain: 'x.com',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [\n        { name: 'url', type: 'string', required: true, positional: true, help: 'The URL of the tweet to unretweet' },\n    ],\n    columns: ['status', 'message'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for twitter unretweet');\n        const target = parseTweetUrl(kwargs.url);\n        await page.goto(target.url);\n        await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n        const result = await page.evaluate(`(async () => {\n        let writeStarted = false;\n        try {\n            ${buildTwitterArticleScopeSource(target.id)}\n            // Poll for the tweet to render. State probes scoped to the article\n            // matching the requested status id — bare querySelector on a\n            // conversation page would silently grab the first article (e.g.\n            // the parent tweet) and unretweet the wrong one.\n            let attempts = 0;\n            let retweetBtn = null;\n            let unretweetBtn = null;\n            let targetArticle = null;\n\n            while (attempts < 20) {\n                targetArticle = findTargetArticle();","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/unretweet.js#L1-L37","documentation":"`twitter unretweet` is a browser-only (Strategy.UI, browser: true) command; its func receives a live `page` from the registry. When there is no active browser session, `page` is falsy and this CommandExecutionError is thrown immediately at the top of func, before any navigation or page interaction. No state on x.com is modified.","triggerScenarios":"Running `opencli twitter unretweet <url>` without a browser session attached: browser not started, running in non-browser mode, browser crashed, or calling func programmatically with page undefined.","commonSituations":"CI environments with no browser configured; user closed the managed browser window; fresh install where the browser binary/profile is not set up; invoking the command through the registry API without session initialization.","solutions":["Ensure a browser session is running and logged into x.com, then re-run `opencli twitter unretweet <tweet-url>`.","Configure a browser-capable (headless or headed) environment if running in CI.","Restart the CLI if the browser session died mid-run.","When embedding, pass a valid page/session object to the command rather than undefined."],"exampleFix":"// before\nopencli twitter unretweet https://x.com/user/status/123  // no session -> error\n// after\nopencli browser start\nopencli twitter unretweet https://x.com/user/status/123","handlingStrategy":"validation","validationCode":"// ensure browser session before unretweet\nconst page = await session.getPage();\nif (!page) await startBrowserSession();\nreturn runCommand('twitter unretweet', { url: tweetUrl });","typeGuard":"function hasBrowserPage(page) {\n  return typeof page === 'object' && page !== null &&\n    typeof page.goto === 'function' && typeof page.evaluate === 'function';\n}","tryCatchPattern":"try {\n  await cli.run(['twitter', 'unretweet', tweetUrl]);\n} catch (e) {\n  if (/Browser session required/.test(e.message)) {\n    await startBrowserSession();\n    await cli.run(['twitter', 'unretweet', tweetUrl]);\n  } else throw e;\n}","preventionTips":["Start the browser session before any browser:true twitter command.","Configure a browser in CI/headless environments.","Probe the session with a trivial page.evaluate before write operations.","Restart the CLI promptly if the managed browser window was closed."],"tags":["browser","precondition","twitter","session"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}