FujiwaraChoki/MoneyPrinterV2 · error · RuntimeError

Could not find tweet text box. Ensure you are logged into X

Error message

Could not find tweet text box. Ensure you are logged into X in this Firefox profile.

What it means

RuntimeError raised in Twitter.post after the selector loop failed to locate the tweet compose text box in any iteration (each Exception swallowed by `continue`, leaving text_box None). It almost always means the page never reached a logged-in compose state in this Firefox profile.

Source

Thrown at src/classes/Twitter.py:111

        text_box = None
        text_box_selectors = [
            (By.CSS_SELECTOR, "div[data-testid='tweetTextarea_0'][role='textbox']"),
            (By.XPATH, "//div[@data-testid='tweetTextarea_0']//div[@role='textbox']"),
            (By.XPATH, "//div[@role='textbox']"),
        ]

        for selector in text_box_selectors:
            try:
                text_box = self.wait.until(EC.element_to_be_clickable(selector))
                text_box.click()
                text_box.send_keys(body)
                break
            except Exception:
                continue

        if text_box is None:
            raise RuntimeError(
                "Could not find tweet text box. Ensure you are logged into X in this Firefox profile."
            )


        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

View on GitHub (pinned to 5192af8eca)

Solutions

  1. Open Firefox with the same profile non-headless and confirm you are logged into X
  2. Re-run login flow / restore session cookies in the profile
  3. Update text_box_selectors to match current X compose DOM (inspect with devtools)
  4. Increase wait/timeout or use WebDriverWait with expected_conditions instead of a fixed loop

Example fix

# before
for sel in text_box_selectors:
    try:
        text_box = driver.find_element(By.CSS_SELECTOR, sel)
        text_box.send_keys(body)
        break
    except Exception:
        continue
# after
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
box = WebDriverWait(driver, 30).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "div[data-testid='tweetTextarea_0']"))
)
box.send_keys(body)
Defensive patterns

Strategy: try-catch

Validate before calling

from selenium.webdriver.common.by import By
found = driver.find_elements(By.CSS_SELECTOR, "div[data-testid='tweetTextarea_0']")
assert found, "compose box absent — check login state"

Try / catch

try:
    twitter.post(body)
except RuntimeError as e:
    if "tweet text box" in str(e):
        # re-login or refresh profile session, then retry once
        ...

Prevention

When it happens

Trigger: Calling post() when the X/Twitter session in the Firefox profile is logged out, the compose URL/DOM changed so all text_box_selectors miss, or the page had not finished loading within the wait loop.

Common situations: Expired X session cookie in the profile, X A/B-tested new compose markup, slow network causing timeout before the box renders, or headless mode being detected.

Related errors


AI-assisted analysis of FujiwaraChoki/MoneyPrinterV2@5192af8eca (2026-08-28). Data as JSON: /api/errors/32d734b9519f9d4d. Report an issue: GitHub.