{"record":{"id":"658924bc5fb6033e","repo":"jackwener/OpenCLI","slug":"twitter-quote","errorCode":null,"errorMessage":"twitter quote","messagePattern":"twitter quote","errorType":"exception","errorClass":"TimeoutError","httpStatus":null,"severity":"error","filePath":"clis/twitter/quote.js","lineNumber":160,"sourceCode":"                cleanupDir = downloaded.cleanupDir;\n            }\n\n            // Dedicated composer is more reliable than the inline quote-tweet button.\n            await page.goto(`https://x.com/compose/post?url=${encodeURIComponent(target.url)}`, { waitUntil: 'load', settleMs: 2500 });\n            await page.wait({ selector: '[data-testid=\"tweetTextarea_0\"]', timeout: 15 });\n\n            if (localImagePath) {\n                await page.wait({ selector: COMPOSER_FILE_INPUT_SELECTOR, timeout: 20 });\n                await attachComposerImage(page, localImagePath);\n            }\n\n            const result = await submitQuote(page, kwargs.text, target.id);\n            if (result.ok) {\n                // Wait for network submission to complete\n                await page.wait(3);\n            }\n            if (result.unconfirmed) {\n                throw new TimeoutError('twitter quote', SUBMIT_TIMEOUT_MS / 1000, `${result.message} Check your profile before retrying; the quote may already be live.`);\n            }\n            if (!result.ok) {\n                throw new CommandExecutionError(result.message, 'Nothing was posted. Open the tweet in the browser and retry.');\n            }\n            return [{\n                    status: 'success',\n                    message: result.message,\n                    text: kwargs.text,\n                    ...(kwargs.image ? { image: kwargs.image } : {}),\n                    ...(kwargs['image-url'] ? { 'image-url': kwargs['image-url'] } : {}),\n                }];\n        } finally {\n            if (cleanupDir) {\n                fs.rmSync(cleanupDir, { recursive: true, force: true });\n            }\n        }\n    }\n});","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/quote.js#L142-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isTimeoutError(e) {\n  return e instanceof TimeoutError || e.name === 'TimeoutError';\n}","tryCatchPattern":"try {\n  await cli.run('twitter quote', kwargs);\n} catch (e) {\n  if (e instanceof TimeoutError) {\n    // do NOT auto-retry: the quote may already be live; verify first\n    const posted = await checkProfileForQuote(tweetText);\n    if (!posted) return cli.run('twitter quote', kwargs);\n    return; // already posted\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["timeout","unconfirmed-state","twitter-api","idempotency"],"backgroundTag":"operation-unconfirmed-timeout","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}