Bug Description
opencli twitter post --images <path> "<text>" reports a failure with message "Tweet submission did not complete before timeout." even though the tweet (with image) is actually posted successfully.
Steps to Reproduce
opencli twitter post "test tweet" --images /path/to/image.png --trace on
Expected Behavior
The command should return status: success with the tweet URL and ID.
Actual Behavior
Returns status: failed with message "Tweet submission did not complete before timeout." — but the tweet is live on the timeline with the image attached.
Verified by running opencli twitter thread <id> afterwards — the tweet exists with has_media: true.
Root Cause Analysis
In clis/twitter/post.js, the submitTweet() function (line 145-196) polls after clicking the tweet button:
- After a successful post, X navigates away from
/compose/post back to the home timeline
- The composer textarea (
tweetTextarea_0) no longer contains the original text → composerStillHasText is false
- However,
hasMedia on line 188-189 matches tweetPhoto elements in the timeline (not just the composer), so hasMedia becomes true
- Since
!composerStillHasText && !hasMedia is never true (hasMedia is true from timeline), the loop keeps running until timeout
The fix should scope the hasMedia check to the composer context only, not the entire page. For example, query within a composer ancestor element, or check if we are still on /compose/post before evaluating media.
Alternatively, detecting the page navigation away from /compose/post to home (or finding the new tweet in the timeline matching the posted text) could serve as a success signal.
Environment
- OpenCLI: v1.8.0
- OS: macOS 26.5
- Node.js: latest bundled with opencli
- Browser: Chromium via opencli built-in
Bug Description
opencli twitter post --images <path> "<text>"reports a failure with message "Tweet submission did not complete before timeout." even though the tweet (with image) is actually posted successfully.Steps to Reproduce
opencli twitter post "test tweet" --images /path/to/image.png --trace onExpected Behavior
The command should return
status: successwith the tweet URL and ID.Actual Behavior
Returns
status: failedwith message"Tweet submission did not complete before timeout."— but the tweet is live on the timeline with the image attached.Verified by running
opencli twitter thread <id>afterwards — the tweet exists withhas_media: true.Root Cause Analysis
In
clis/twitter/post.js, thesubmitTweet()function (line 145-196) polls after clicking the tweet button:/compose/postback to the home timelinetweetTextarea_0) no longer contains the original text →composerStillHasTextisfalsehasMediaon line 188-189 matchestweetPhotoelements in the timeline (not just the composer), sohasMediabecomestrue!composerStillHasText && !hasMediais never true (hasMedia is true from timeline), the loop keeps running until timeoutThe fix should scope the
hasMediacheck to the composer context only, not the entire page. For example, query within a composer ancestor element, or check if we are still on/compose/postbefore evaluating media.Alternatively, detecting the page navigation away from
/compose/postto home (or finding the new tweet in the timeline matching the posted text) could serve as a success signal.Environment