{"record":{"id":"bae4e690e8b34d4e","repo":"FujiwaraChoki/MoneyPrinterV2","slug":"could-not-find-the-post-button-on-x-compose-screen","errorCode":null,"errorMessage":"Could not find the Post button on X compose screen.","messagePattern":"Could not find the Post button on X compose screen\\.","errorType":"error_code","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/classes/Twitter.py","lineNumber":132,"sourceCode":"\n\n        post_button = None\n        post_button_selectors = [\n            (By.XPATH, \"//button[@data-testid='tweetButtonInline']\"),\n            (By.XPATH, \"//button[@data-testid='tweetButton']\"),\n            (By.XPATH, \"//span[text()='Post']/ancestor::button\"),\n        ]\n\n        for selector in post_button_selectors:\n            try:\n                post_button = self.wait.until(EC.element_to_be_clickable(selector))\n                post_button.click()\n                break\n            except Exception:\n                continue\n\n        if post_button is None:\n            raise RuntimeError(\"Could not find the Post button on X compose screen.\")\n\n        if verbose:\n            print(colored(\" => Pressed [ENTER] Button on Twitter..\", \"blue\"))\n        time.sleep(2)\n\n        # Add the post to the cache\n        self.add_post({\"content\": body, \"date\": now.strftime(\"%m/%d/%Y, %H:%M:%S\")})\n\n        success(\"Posted to Twitter successfully!\")\n\n    def get_posts(self) -> List[dict]:\n        \"\"\"\n        Gets the posts from the cache.\n\n        Returns:\n            posts (List[dict]): The posts\n        \"\"\"\n        if not os.path.exists(get_twitter_cache_path()):","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/FujiwaraChoki/MoneyPrinterV2/blob/5192af8eca97759f941834b947e3ceb209da0649/src/classes/Twitter.py#L114-L150","documentation":"RuntimeError raised in Twitter.post when none of the post_button_selectors could be found/clicked, leaving post_button None after the swallow-and-continue loop. The tweet text was entered but the compose screen's Post button never became clickable.","triggerScenarios":"Calling post() where the Post button is disabled (empty/rate-limited compose), the button's data-testid changed, an overlay/modal intercepts clicks, or the loop times out before the button renders.","commonSituations":"X UI updates renaming the button selector, headless rendering differences, slow load after typing, or a draft-state modal blocking the button.","solutions":["Inspect the live compose DOM and update post_button_selectors with the current button selector (e.g. button[data-testid='tweetButton'])","Wait for button to be enabled (check aria-disabled/disabled attr) before clicking","Dismiss overlay modals or use JS click as fallback","Add WebDriverWait-based clickable condition with a longer timeout"],"exampleFix":"# before\nfor sel in post_button_selectors:\n    try:\n        post_button.click()\n        break\n    except Exception:\n        continue\n# after\nfrom selenium.webdriver.support.ui import WebDriverWait\nfrom selenium.webdriver.support import expected_conditions as EC\nbtn = WebDriverWait(driver, 30).until(\n    EC.element_to_be_clickable((By.CSS_SELECTOR, \"button[data-testid='tweetButton']:not([disabled])\"))\n)\nbtn.click()","handlingStrategy":"try-catch","validationCode":"from selenium.webdriver.common.by import By\nbtns = driver.find_elements(By.CSS_SELECTOR, \"button[data-testid='tweetButton']\")\nassert btns and btns[0].is_enabled(), \"Post button not ready\"","typeGuard":null,"tryCatchPattern":"try:\n    twitter.post(body)\nexcept RuntimeError as e:\n    if \"Post button\" in str(e):\n        driver.refresh(); twitter.post(body)  # one retry","preventionTips":["Wait for the button to be enabled before clicking","Verify text actually landed in the compose box first","Keep selectors current with X's DOM"],"tags":["selenium","twitter","dom-selector","button-click"],"backgroundTag":"ui-selector-not-found","analyzedSha":"5192af8eca97759f941834b947e3ceb209da0649","analyzedAt":"2026-08-28T10:31:46.474Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}