jackwener/OpenCLI · error · CommandExecutionError

Nothing was posted. Open the tweet in the browser and retry.

Error message

Nothing was posted. Open the tweet in the browser and retry.

What it means

CommandExecutionError thrown when submitQuote returned result.ok === false, meaning the quote tweet definitively failed and nothing was posted. Unlike the unconfirmed/timeout case, no side effect occurred, so the fix message tells the user to open the tweet in the browser and retry.

Source

Thrown at clis/twitter/quote.js:163

            // Dedicated composer is more reliable than the inline quote-tweet button.
            await page.goto(`https://x.com/compose/post?url=${encodeURIComponent(target.url)}`, { waitUntil: 'load', settleMs: 2500 });
            await page.wait({ selector: '[data-testid="tweetTextarea_0"]', timeout: 15 });

            if (localImagePath) {
                await page.wait({ selector: COMPOSER_FILE_INPUT_SELECTOR, timeout: 20 });
                await attachComposerImage(page, localImagePath);
            }

            const result = await submitQuote(page, kwargs.text, target.id);
            if (result.ok) {
                // Wait for network submission to complete
                await page.wait(3);
            }
            if (result.unconfirmed) {
                throw new TimeoutError('twitter quote', SUBMIT_TIMEOUT_MS / 1000, `${result.message} Check your profile before retrying; the quote 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,
                    ...(kwargs.image ? { image: kwargs.image } : {}),
                    ...(kwargs['image-url'] ? { 'image-url': kwargs['image-url'] } : {}),
                }];
        } finally {
            if (cleanupDir) {
                fs.rmSync(cleanupDir, { recursive: true, force: true });
            }
        }
    }
});

export const __test__ = {
    buildQuoteComposerUrl,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Read the accompanying result.message for the concrete failure reason and fix the input (text length, media)
  2. Retry the command after verifying the tweet was not posted
  3. Manually perform the quote in the browser to check for account-level restrictions (rate limit, suspension)
  4. Update the library if x.com UI changes broke the submit flow selectors
Defensive patterns

Strategy: try-catch

Validate before calling

if (!kwargs.text || kwargs.text.length > 280) {
  throw new Error('Quote text must be 1-280 characters');
}

Try / catch

try {
  await cli.run('twitter quote', kwargs);
} catch (e) {
  if (e instanceof CommandExecutionError && /Nothing was posted/.test(e.message)) {
    // definitive failure: safe to retry after fixing the cause in e.message
    logFailure(e.message);
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: The submit flow detected explicit failure (post button click rejected, error state in the page, or validation failure in result.message) — submitQuote resolved with ok:false and a reason message.

Common situations: x.com showing 'Something went wrong' during posting; text/media rejected; rate limits or account restrictions on posting; DOM changes making the submit click ineffective; empty or oversized tweet text.

Related errors


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