jackwener/OpenCLI · error · TimeoutError
twitter quote
Error message
twitter quote
What it means
TimeoutError('twitter quote', ...) thrown when submitQuote finished with result.unconfirmed — the quote tweet could not be confirmed as posted within SUBMIT_TIMEOUT_MS. Because the request may have actually gone through, the error message instructs the user to check their profile before retrying to avoid duplicate quotes.
Source
Thrown at clis/twitter/quote.js:160
cleanupDir = downloaded.cleanupDir;
}
// 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 });
}
}
}
});View on GitHub (pinned to 49907e53dc)
Solutions
- Check your x.com profile to see whether the quote actually posted before retrying (avoid duplicates)
- Increase SUBMIT_TIMEOUT_MS if submissions are consistently slow
- Re-run after confirming the quote is absent; if present, skip retrying
- Update the library if x.com changed the confirmation signal (toast/URL pattern) that detection relies on
Defensive patterns
Strategy: try-catch
Type guard
function isTimeoutError(e) {
return e instanceof TimeoutError || e.name === 'TimeoutError';
} Try / catch
try {
await cli.run('twitter quote', kwargs);
} catch (e) {
if (e instanceof TimeoutError) {
// do NOT auto-retry: the quote may already be live; verify first
const posted = await checkProfileForQuote(tweetText);
if (!posted) return cli.run('twitter quote', kwargs);
return; // already posted
}
throw e;
} Prevention
- Never blind-retry after this timeout — check the profile for the quote first
- Use a generous SUBMIT_TIMEOUT_MS on slow connections
- Verify via the profile/timeline before resubmitting to avoid duplicates
- Keep the library updated against x.com confirmation-signal changes
When it happens
Trigger: The quote submit flow (clicking the post button / awaiting confirmation) did not yield a verifiable success within SUBMIT_TIMEOUT_MS seconds — slow network, x.com UI change, or the confirmation signal (new tweet URL) never appeared.
Common situations: Slow or flaky connection during submission; x.com DOM/network response changes breaking confirmation detection; rate-limiting delaying the post; long-running batch scripts hitting the timeout at scale.
Related errors
- ${result.message} Check muted words before retrying; the wor
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- ${config.site} login
- Timeout waiting for Antigravity reply after ${timeout / 1000
- FETCH_ERROR
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/658924bc5fb6033e.
Report an issue: GitHub.