FujiwaraChoki/MoneyPrinterV2 · error · RuntimeError
Could not find the Post button on X compose screen.
Error message
Could not find the Post button on X compose screen.
What it means
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.
Source
Thrown at src/classes/Twitter.py:132
post_button = None
post_button_selectors = [
(By.XPATH, "//button[@data-testid='tweetButtonInline']"),
(By.XPATH, "//button[@data-testid='tweetButton']"),
(By.XPATH, "//span[text()='Post']/ancestor::button"),
]
for selector in post_button_selectors:
try:
post_button = self.wait.until(EC.element_to_be_clickable(selector))
post_button.click()
break
except Exception:
continue
if post_button is None:
raise RuntimeError("Could not find the Post button on X compose screen.")
if verbose:
print(colored(" => Pressed [ENTER] Button on Twitter..", "blue"))
time.sleep(2)
# Add the post to the cache
self.add_post({"content": body, "date": now.strftime("%m/%d/%Y, %H:%M:%S")})
success("Posted to Twitter successfully!")
def get_posts(self) -> List[dict]:
"""
Gets the posts from the cache.
Returns:
posts (List[dict]): The posts
"""
if not os.path.exists(get_twitter_cache_path()):View on GitHub (pinned to 5192af8eca)
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
Example fix
# before
for sel in post_button_selectors:
try:
post_button.click()
break
except Exception:
continue
# after
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
btn = WebDriverWait(driver, 30).until(
EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='tweetButton']:not([disabled])"))
)
btn.click() Defensive patterns
Strategy: try-catch
Validate before calling
from selenium.webdriver.common.by import By btns = driver.find_elements(By.CSS_SELECTOR, "button[data-testid='tweetButton']") assert btns and btns[0].is_enabled(), "Post button not ready"
Try / catch
try:
twitter.post(body)
except RuntimeError as e:
if "Post button" in str(e):
driver.refresh(); twitter.post(body) # one retry Prevention
- 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
When it happens
Trigger: 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.
Common situations: X UI updates renaming the button selector, headless rendering differences, slow load after typing, or a draft-state modal blocking the button.
Related errors
- Could not find tweet text box. Ensure you are logged into X
- Firefox profile path does not exist or is not a directory: {
- Firefox profile path does not exist or is not a directory: {
- Firefox profile path does not exist or is not a directory: {
AI-assisted analysis of FujiwaraChoki/MoneyPrinterV2@5192af8eca (2026-08-28).
Data as JSON: /api/errors/bae4e690e8b34d4e.
Report an issue: GitHub.