{"record":{"id":"7f7f3bb822871d9f","repo":"jackwener/OpenCLI","slug":"twitter-tweet-url-cannot-be-empty","errorCode":null,"errorMessage":"twitter tweet URL cannot be empty","messagePattern":"twitter tweet URL cannot be empty","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/twitter/shared.js","lineNumber":50,"sourceCode":"    'messages',\n    'notifications',\n    'privacy',\n    'search',\n    'settings',\n    'signup',\n    'tos',\n]);\n\nfunction isTwitterHost(hostname) {\n    return TWEET_HOSTS.has(hostname)\n        || hostname.endsWith('.x.com')\n        || hostname.endsWith('.twitter.com');\n}\n\nexport function parseTweetUrl(rawUrl) {\n    const value = String(rawUrl ?? '').trim();\n    if (!value) {\n        throw new ArgumentError('twitter tweet URL cannot be empty', 'Example: opencli twitter retweet https://x.com/jack/status/20');\n    }\n    let parsed;\n    try {\n        parsed = new URL(value);\n    }\n    catch {\n        throw new ArgumentError(`Invalid tweet URL: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');\n    }\n    const hostname = parsed.hostname.toLowerCase();\n    if (parsed.protocol !== 'https:' || !isTwitterHost(hostname)) {\n        throw new ArgumentError(`Invalid tweet URL host: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');\n    }\n    const match = parsed.pathname.match(TWEET_PATH_PATTERN);\n    if (!match?.[1]) {\n        throw new ArgumentError(`Could not extract tweet ID from URL: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');\n    }\n    return {\n        id: match[1],","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/twitter/shared.js#L32-L68","documentation":"ArgumentError from parseTweetUrl when the URL argument is empty or whitespace-only. parseTweetUrl is the shared validator used by retweet, like, quote and other tweet-targeting commands, so all of them fail fast with this error before any browser interaction.","triggerScenarios":"`opencli twitter retweet ''`, passing an unset shell variable ($TWEET_URL expands to nothing), or calling the JS API with null/undefined/'' as rawUrl.","commonSituations":"CI variables not set, copy-paste losing the URL, scripts interpolating an empty field from JSON/YAML input, or forgetting the positional argument entirely.","solutions":["Pass a full tweet URL as the argument, e.g. https://x.com/jack/status/20","Fix the shell/CI variable so it is non-empty before invoking","Quote the URL to prevent the shell from eating it"],"exampleFix":"// before\nopencli twitter retweet \"$TWEET_URL\"   # TWEET_URL empty\n// after\nTWEET_URL=https://x.com/jack/status/20 opencli twitter retweet \"$TWEET_URL\"","handlingStrategy":"validation","validationCode":"function requireTweetUrl(v) {\n  const s = String(v ?? '').trim();\n  if (!s) throw new Error('tweet URL is required, e.g. https://x.com/jack/status/20');\n  return s;\n}","typeGuard":"function hasTweetUrl(v) { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":"try {\n  await opencli.twitter.retweet(url);\n} catch (e) {\n  if (e.name === 'ArgumentError' && /cannot be empty/.test(e.message)) {\n    console.error('Provide a full tweet URL');\n  } else throw e;\n}","preventionTips":["Validate env/config variables are non-empty before invoking","Quote URLs in shell commands","Require the positional argument in wrapper scripts","Fail fast in CI if TWEET_URL is unset"],"tags":["validation","argument","twitter","empty-input"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}