{"record":{"id":"4b7283b9e1634c75","repo":"jackwener/OpenCLI","slug":"browser-session-required-for-twitter-unbookmark","errorCode":null,"errorMessage":"Browser session required for twitter unbookmark","messagePattern":"Browser session required for twitter unbookmark","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/unbookmark.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: 'unbookmark',\n    access: 'write',\n    description: 'Remove a tweet from bookmarks',\n    domain: 'x.com',\n    strategy: Strategy.UI,\n    browser: true,\n    args: [\n        { name: 'url', type: 'string', positional: true, required: true, help: 'Tweet URL to unbookmark' },\n    ],\n    columns: ['status', 'message'],\n    func: async (page, kwargs) => {\n        if (!page)\n            throw new CommandExecutionError('Browser session required for twitter unbookmark');\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            let attempts = 0;\n            let removeBtn = null;\n            let targetArticle = null;\n\n            while (attempts < 20) {\n                targetArticle = findTargetArticle();\n                // Check if not bookmarked (already removed)\n                const bookmarkBtn = targetArticle?.querySelector('[data-testid=\"bookmark\"]');\n                if (bookmarkBtn) {\n                    return { ok: true, message: 'Tweet is not bookmarked (already removed).' };\n                }","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/unbookmark.js#L1-L37","documentation":"CommandExecutionError (code COMMAND_EXEC) thrown by `twitter unbookmark` because bookmark removal is a browser-write command requiring an interactive page on the logged-in X session. With page null the library fails fast instead of attempting a non-browser path. The message mirrors the sibling unblock/unfollow guards.","triggerScenarios":"Running `twitter unbookmark <tweet-url>` without an active browser session, so `func` receives page === null/undefined at the guard on line 19.","commonSituations":"Invoking the CLI headlessly or from scripts without connecting the browser; CI environments with no logged-in Chrome profile; forgetting to log in to x.com before write commands.","solutions":["Connect/start a browser session and log in to x.com, then re-run `twitter unbookmark`","Run the command interactively rather than in API-only/headless mode","In scripts, verify browser session availability before invoking and emit a clear prerequisite error"],"exampleFix":"// before\nawait cli.run(['twitter', 'unbookmark', tweetUrl]); // no browser session\n// after\nconst page = await getBrowserPage('x.com');\nif (!page) throw new Error('Start a browser session and log in to x.com first');\nawait cli.run(['twitter', 'unbookmark', tweetUrl]);","handlingStrategy":"validation","validationCode":"if (!browserSession || !browserSession.page) {\n  throw new Error('Start a browser session and log in to x.com before running twitter unbookmark');\n}","typeGuard":"function hasBrowserPage(ctx) { return ctx != null && typeof ctx.page === 'object' && ctx.page !== null; }","tryCatchPattern":"try {\n  await cli.run(['twitter', 'unbookmark', tweetUrl]);\n} catch (e) {\n  if (e.code === 'COMMAND_EXEC' && /Browser session required/.test(e.message)) {\n    console.error('Connect a browser session and log in to x.com first');\n  } else throw e;\n}","preventionTips":["Bootstrap the browser session and x.com login before any bookmark write","Validate the tweet URL parses (parseTweetUrl) before invoking","Skip browser-write commands in headless pipelines or provision a logged-in profile there","Keep one verified login step ahead of all twitter write commands in scripts"],"tags":["twitter","browser-session","precondition","write-command"],"backgroundTag":"browser-session-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}