jackwener/OpenCLI · error · TimeoutError

twitter reply

Error message

twitter reply

What it means

This is the timeout path of the reply submit: after inserting text and clicking Reply, the submit poller ran for SUBMIT_TIMEOUT_MS (15s) without confirming the reply posted (result.unconfirmed). The command throws a TimeoutError labeled 'twitter reply' with the poller's message and a warning that the reply may already be live, so blind retries risk duplicate replies.

Source

Thrown at clis/twitter/reply.js:291

                const downloaded = await downloadRemoteImage(kwargs['image-url']);
                localImagePath = downloaded.absPath;
                cleanupDir = downloaded.cleanupDir;
            }
            // Dedicated composer is normally more reliable than the inline
            // tweet page reply box, but X occasionally leaves that route on the
            // Home timeline behind a loading dialog. openReplyComposer falls
            // back to the target tweet's visible Reply action.
            const composer = await openReplyComposer(page, kwargs.url);
            if (!composer?.ok) {
                throw new CommandExecutionError(composer?.message ?? 'Could not open the reply composer.', 'Open the tweet in the browser and check whether the reply box is available.');
            }
            if (localImagePath) {
                await page.wait({ selector: COMPOSER_FILE_INPUT_SELECTOR, timeout: 20 });
                await attachComposerImage(page, localImagePath);
            }
            const result = await submitReply(page, kwargs.text);
            if (result.unconfirmed) {
                throw new TimeoutError('twitter reply', SUBMIT_TIMEOUT_MS / 1000, `${result.message} Check the tweet before retrying; the reply may already be live.`);
            }
            if (!result.ok) {
                throw new CommandExecutionError(result.message, 'Nothing was posted. Open the tweet in the browser and retry.');
            }
            return [{
                    status: 'success',
                    message: result.message,
                    text: kwargs.text,
                    ...(result.url ? { url: result.url } : {}),
                    ...(kwargs.image ? { image: kwargs.image } : {}),
                    ...(kwargs['image-url'] ? { 'image-url': kwargs['image-url'] } : {}),
                }];
        } finally {
            if (cleanupDir) {
                fs.rmSync(cleanupDir, { recursive: true, force: true });
            }
        }
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the tweet (or your profile's Replies tab) before retrying — the reply may already be live and retrying duplicates it.
  2. Retry the command once; a second attempt usually confirms quickly if the first actually posted.
  3. Increase SUBMIT_TIMEOUT_MS if your environment is consistently slow (e.g. 30_000).
  4. Verify the account is not rate-limited or logged out.

Example fix

// before
const SUBMIT_TIMEOUT_MS = 15_000;
// after
const SUBMIT_TIMEOUT_MS = 30_000; // slow networks / delayed X confirmation
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure non-empty, within-length text before invoking:
if (!text || text.length > 280) throw new Error('Reply text empty or too long');

Type guard

null

Try / catch

try {
  await cli('twitter', 'reply', { url, text });
} catch (e) {
  if (e.name === 'TimeoutError' && String(e.message).includes('twitter reply')) {
    // DO NOT retry immediately: verify the reply didn't post first
    const posted = await checkProfileReplies(url);
    if (!posted) await cli('twitter', 'reply', { url, text });
  } else throw e;
}

Prevention

When it happens

Trigger: submitReply's 15-second polling loop ends without detecting the success state or a status URL — slow network, a stuck compose dialog, an error toast X shows slowly, or the success permalink element not appearing in time.

Common situations: Slow connection or heavy page load pushing confirmation past 15s; X showing a transient error banner ('Something went wrong') that the poller never resolves; rate limiting delaying post creation.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/f6c90d9d0c74899f. Report an issue: GitHub.