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
- Read the accompanying result.message for the concrete failure reason and fix the input (text length, media)
- Retry the command after verifying the tweet was not posted
- Manually perform the quote in the browser to check for account-level restrictions (rate limit, suspension)
- 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
- Keep quote text within Twitter limits and media valid before submitting
- Watch for account rate limits; space out submissions in batch runs
- Inspect result.message for the concrete cause before retrying
- Update the library if submit selectors break after x.com UI changes
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
- ${send?.reason || 'Failed to send Grok prompt'}
- rawResult.error + (rawResult.hint ? ` (${rawResult.hint})` :
- HTTP ${userLookup.error}: Failed to resolve Twitter user @${
- Following
- Could not verify list removal: unexpected lists payload shap
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/14f778915f4d7fd4.
Report an issue: GitHub.