Skip to content

twitter reply fails with: 'Could not find the reply text area' #848

@winfred5432

Description

@winfred5432

Repro

On a logged-in Chrome session where opencli doctor passes and opencli twitter post "..." works, run:

opencli twitter reply "https://x.com/<user>/status/<tweet_id>" "hello"

Observed output:

- status: failed
  message: Could not find the reply text area. Are you logged in?

What I checked

As of April 7, 2026, the current source already calls page.goto(kwargs.url) in clis/twitter/reply.ts for text-only replies, so this does not look like a simple “missing navigation” bug.

The more likely problem is the wait condition:

  • text-only flow does:
    • await page.goto(kwargs.url)
    • await page.wait({ selector: '[data-testid="primaryColumn"]' })
    • then immediately queries document.querySelector('[data-testid="tweetTextarea_0"]')
  • but on X, primaryColumn is not specific to the reply composer
  • the inline reply textarea can appear later than primaryColumn, or the SPA can still be settling when the selector check runs
  • result: reply fails with Could not find the reply text area even though the user is logged in

Suggested fix

Use the dedicated reply composer for all replies (not only image replies), and wait for the actual reply textarea before typing:

diff --git a/clis/twitter/reply.ts b/clis/twitter/reply.ts
@@
-      if (localImagePath) {
-        await page.goto(buildReplyComposerUrl(kwargs.url));
-        await page.wait({ selector: '[data-testid="tweetTextarea_0"]' });
-        await page.wait({ selector: REPLY_FILE_INPUT_SELECTOR, timeout: 20 });
-        await attachReplyImage(page, localImagePath);
-      } else {
-        await page.goto(kwargs.url);
-        await page.wait({ selector: '[data-testid="primaryColumn"]' });
-      }
+      await page.goto(buildReplyComposerUrl(kwargs.url), { waitUntil: 'load', settleMs: 2500 });
+      await page.wait({ selector: '[data-testid="tweetTextarea_0"]', timeout: 8 });
+      if (localImagePath) {
+        await page.wait({ selector: REPLY_FILE_INPUT_SELECTOR, timeout: 20 });
+        await attachReplyImage(page, localImagePath);
+      }

Why this helps

  • avoids relying on the inline tweet-page reply box
  • waits on the actual composer needed by the command
  • makes text-only and image reply paths consistent
  • matches the user-visible failure mode more closely than a login problem

Validation

I applied the patch locally and the existing adapter test file still passes after updating expectations:

npx vitest run --project adapter clis/twitter/reply.test.ts

Result:

Test Files  1 passed (1)
Tests       7 passed (7)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions