{"record":{"id":"9219fed77bd49de4","repo":"jackwener/OpenCLI","slug":"twitter-download-failed-err-message-string","errorCode":null,"errorMessage":"twitter download failed: ${err?.message ?? String(err)}","messagePattern":"twitter download failed: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/twitter/download.js","lineNumber":340,"sourceCode":"            if (!rawUsername && !tweetUrl) {\n                throw new ArgumentError('twitter download requires either <username> or --tweet-url');\n            }\n            if (rawUsername && tweetUrl) {\n                throw new ArgumentError('Use either <username> or --tweet-url, not both');\n            }\n            if (tweetUrl) {\n                return downloadSingleTweet(page, tweetUrl, output);\n            }\n            const limit = requireLimit(kwargs.limit);\n            const username = normalizeTwitterScreenName(rawUsername);\n            if (!username) {\n                throw new ArgumentError('twitter download username must be a valid Twitter/X handle', 'Example: opencli twitter download @jack --limit 20');\n            }\n            return downloadUserMedia(page, username, limit, output);\n        }\n        catch (err) {\n            if (err instanceof CliError) throw err;\n            throw new CommandExecutionError(`twitter download failed: ${err?.message ?? String(err)}`);\n        }\n    },\n});\n\nasync function downloadUserMedia(page, username, limit, output) {\n    await page.goto(`https://x.com/${username}`);\n    await page.wait({ selector: '[data-testid=\"primaryColumn\"]' });\n\n    const cookies = await page.getCookies({ url: 'https://x.com' });\n    const ct0 = cookies.find((c) => c.name === 'ct0')?.value || null;\n    if (!ct0) throw new AuthRequiredError('x.com', 'Not logged into x.com (no ct0 cookie)');\n\n    const userMediaOperation = await resolveTwitterOperationMetadata(page, 'UserMedia', USER_MEDIA_OPERATION);\n    const userByScreenNameOperation = await resolveTwitterOperationMetadata(page, 'UserByScreenName', USER_BY_SCREEN_NAME_OPERATION);\n\n    const headers = JSON.stringify({\n        'Authorization': `Bearer ${decodeURIComponent(TWITTER_BEARER_TOKEN)}`,\n        'X-Csrf-Token': ct0,","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/download.js#L322-L358","documentation":"The command wraps its body in try/catch: any thrown error that is not already a CliError is re-wrapped in a CommandExecutionError whose message is prefixed with 'twitter download failed:'. This catch-all surfaces unexpected failures (browser errors, fetch failures, network issues) with consistent CLI formatting.","triggerScenarios":"Any non-CliError exception inside the download flow: page.goto failures, wait timeouts, page.evaluate syntax/runtime errors, requireFetchPayload rejections on non-OK fetches, or downloadTwitterMedia filesystem/ytdlp errors.","commonSituations":"No network or DNS failure reaching x.com; page load timeout; x.com UI changes breaking selectors; rate limiting causing non-OK HTTP responses; ytdlp missing or failing on video download.","solutions":["Read the embedded original message after the prefix to identify the root cause","Check network connectivity and that x.com is reachable from the browser","Re-run with a fresh logged-in browser session; retry after rate-limit windows","Update the CLI if x.com DOM/GraphQL changed and selectors or operations are stale"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await runTwitterDownload(args);\n} catch (err) {\n  if (err.name === 'CommandExecutionError') {\n    console.error('Root cause:', err.message.replace(/^twitter download failed: /, ''));\n  }\n}","preventionTips":["Ensure network access to x.com before running","Keep the CLI updated against x.com changes","Use a healthy, logged-in browser profile"],"tags":["cli","error-wrapping","runtime-failure","twitter"],"backgroundTag":"command-execution-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}