jackwener/OpenCLI · warning · TimeoutError
twitter post
Error message
twitter post
What it means
TimeoutError thrown when submitTweet could not CONFIRM the tweet went out before SUBMIT_TIMEOUT_MS. Crucially this is ambiguous: the poll expiring does not mean the tweet failed — it may already be live. Retrying blindly risks a duplicate post (issue #2255), so the message directs you to check `opencli twitter tweets --limit 1` first.
Source
Thrown at clis/twitter/post.js:352
if (!uploadState?.ok) {
throw new TimeoutError('twitter image upload', UPLOAD_TIMEOUT_MS / 1000, 'Nothing was posted. Retry, or attach a smaller image.');
}
}
// Insert and verify the text after media upload so text + images are in
// the final Draft.js composer state immediately before clicking Post.
const typeResult = await insertComposerText(page, text);
if (!typeResult?.ok) {
throw new CommandExecutionError(typeResult?.message ?? 'Could not type tweet text.', 'Open the composer in the browser and check whether X is asking you to log in.');
}
await page.wait(1);
const result = await submitTweet(page, text);
if (result?.unconfirmed) {
// The poll expiring does not mean the tweet stayed in the composer,
// so this must not read as a definite failure: the agent workflow
// retries CommandExecutionError and would post twice (#2255).
throw new TimeoutError('twitter post', SUBMIT_TIMEOUT_MS / 1000, `${result.message} Check \`opencli twitter tweets --limit 1\` before retrying; the post may already be live.`);
}
if (!result?.ok) {
throw new CommandExecutionError(result?.message ?? 'Tweet failed to post.', 'Nothing was posted. Open the composer in the browser and retry.');
}
return [{
status: 'success',
message: result.message,
text,
...(result.id ? { id: result.id } : {}),
...(result.url ? { url: result.url } : {}),
}];
}
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Do NOT immediately retry; run `opencli twitter tweets --limit 1` to see if the post is already live
- If the tweet is live, treat the command as successful and skip retry
- If not live, retry the post command once
- Increase the submit timeout or improve network conditions if this recurs
- If confirmations are consistently missed, X may have changed its success indicators — report/update selectors
Example fix
// before
try { await post(); } catch (e) { await post(); } // may double-post
// after
try { await post(); } catch (e) {
const recent = await opencli('twitter tweets', { limit: 1 });
if (!recent.some(t => t.text === expectedText)) await post();
} Defensive patterns
Strategy: retry
Validate before calling
// before retrying, verify the post actually went out
const recent = await opencli('twitter tweets', { limit: 1 });
if (recent?.[0]?.text === expectedText) return; // already live, skip retry Type guard
const isAmbiguousSubmitTimeout = (e) =>
e?.name === 'TimeoutError' && e.message.startsWith('twitter post'); Try / catch
try {
await postTweet({ text });
} catch (e) {
if (isAmbiguousSubmitTimeout(e)) {
const recent = await opencli('twitter tweets', { limit: 1 });
if (recent?.[0]?.text !== text) await postTweet({ text });
return;
}
throw e;
} Prevention
- Never blind-retry on this timeout — check tweets --limit 1 first (duplicate risk, #2255)
- Deduplicate by comparing the most recent tweet's text before re-posting
- Post on a stable network connection
- Track posted texts in a local ledger to detect duplicates
When it happens
Trigger: submitTweet returns { unconfirmed: true } — clicking Post did not yield a confirmation (toast/permalink) within SUBMIT_TIMEOUT_MS, e.g. slow X response, network hiccup after the click, or confirmation UI changes.
Common situations: Slow network right after clicking Post; X confirmation toast delayed or suppressed; agent automation retry loops causing duplicate tweets when the error is treated as a definite failure.
Related errors
- Unexpected 12306 probe: ${JSON.stringify(probe)}
- twitter follow confirmation
- twitter followers API capture
- twitter like confirmation
- ${result.message} Check muted words before retrying; the wor
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/937cd2fe4cdef836.
Report an issue: GitHub.