{"record":{"id":"c1de709f72c1df97","repo":"jackwener/OpenCLI","slug":"twitter-follow-confirmation","errorCode":null,"errorMessage":"twitter follow confirmation","messagePattern":"twitter follow confirmation","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"warning","filePath":"clis/twitter/follow.js","lineNumber":63,"sourceCode":"            }\n\n            writeStarted = true;\n            followBtn.click();\n            await new Promise(r => setTimeout(r, 1500));\n\n            // Verify\n            const verify = document.querySelector('[data-testid$=\"-unfollow\"]');\n            if (verify) {\n                return { ok: true, message: 'Successfully followed @${username}.' };\n            } else {\n                return { ok: false, unconfirmed: true, message: 'Follow action initiated but UI did not update.' };\n            }\n        } catch (e) {\n            return { ok: false, unconfirmed: writeStarted, message: e.toString() };\n        }\n    })()`);\n        if (result.unconfirmed) {\n            throw new TimeoutError('twitter follow confirmation', 1.5, `${result.message} Check the profile before retrying; the follow may already have succeeded.`);\n        }\n        if (!result.ok) {\n            throw new CommandExecutionError(result.message, 'Nothing changed. Open the profile in the browser and retry.');\n        }\n        await page.wait(2);\n        return [{\n                status: 'success',\n                message: result.message\n            }];\n    }\n});\n","sourceCodeStart":45,"sourceCodeEnd":75,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/follow.js#L45-L75","documentation":"After running the in-page follow flow, the command checks result.unconfirmed — set when the follow button's write had started but the confirmation (button-state change / toast) was never observed within the 1.5s window because the evaluate caught an exception. It throws TimeoutError('twitter follow confirmation', 1.5) with a hint that the follow may already have succeeded, so users check the profile before retrying to avoid double-follow side effects.","triggerScenarios":"The in-page follow script threw after writeStarted = true (e.g. the confirmation selector/toast never appeared, X's UI updated, or the page navigated); slow network or X latency means confirmation takes longer than the 1.5s window; a modal or rate-limit interstitial blocked the confirmation signal.","commonSituations":"Slow connections where the button state flip takes >1.5s; X A/B UI changes moving the confirmation indicator; the target account is protected/private so the follow enters a pending state that the script does not recognize; rate limiting altering the response.","solutions":["Open https://x.com/<username> in the browser and check whether you already follow the account before retrying — the write likely succeeded.","Simply retry the command; if already following, the follow flow will report the existing state rather than re-following.","Check for X UI changes or interstitials (rate-limit modal, login prompt) in the browser that block the confirmation signal.","Retry when the network is faster; persistent unconfirmed timeouts on a stable connection suggest a stale extractor (update/report)."],"exampleFix":"// before\n// timeout on slow network -> assume failure, follow again\n// after\n// 1) verify at https://x.com/<username> whether the follow landed\n// 2) only retry if not already following","handlingStrategy":"retry","validationCode":"// No pre-call check can fully prevent this; reduce likelihood by ensuring a\n// fast, stable connection and no X interstitials before invoking:\nasync function pageLooksClean(page) {\n  await page.wait({ selector: '[data-testid=\"primaryColumn\"]' }); // page fully loaded\n  return true;\n}","typeGuard":"function isConfirmedFollowResult(r) {\n  return typeof r === 'object' && r !== null && r.ok === true && !r.unconfirmed;\n}","tryCatchPattern":"try {\n  await follow(username);\n} catch (e) {\n  if (e.code === 'TIMEOUT' && e.message.includes('twitter follow confirmation')) {\n    // The write may have landed — verify before retrying to avoid confusion\n    const following = await checkFollowingOnProfile(username); // manual or scripted\n    if (!following) return retryWithBackoff(follow, username);\n    return; // already followed\n  }\n  throw e;\n}","preventionTips":["After an unconfirmed timeout, always check the profile before re-running — the follow may have succeeded.","Run on a stable connection; confirmation is observed within a short 1.5s window.","Watch for X UI/AB-test changes that move the confirmation indicator; keep the CLI updated.","Handle protected accounts: pending follow requests may never confirm like normal follows."],"tags":["timeout","twitter","ui-automation","unconfirmed-write"],"backgroundTag":"unconfirmed-write-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}