jackwener/OpenCLI · error · ArgumentError

Invalid tweet URL: ${value}

Error message

Invalid tweet URL: ${value}

What it means

ArgumentError from parseTweetUrl when the string is non-empty but cannot be parsed as a URL (new URL(value) throws). The library rejects it early with guidance to use a full https://x.com/<user>/status/<id> URL.

Source

Thrown at clis/twitter/shared.js:57

]);

function isTwitterHost(hostname) {
    return TWEET_HOSTS.has(hostname)
        || hostname.endsWith('.x.com')
        || hostname.endsWith('.twitter.com');
}

export function parseTweetUrl(rawUrl) {
    const value = String(rawUrl ?? '').trim();
    if (!value) {
        throw new ArgumentError('twitter tweet URL cannot be empty', 'Example: opencli twitter retweet https://x.com/jack/status/20');
    }
    let parsed;
    try {
        parsed = new URL(value);
    }
    catch {
        throw new ArgumentError(`Invalid tweet URL: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');
    }
    const hostname = parsed.hostname.toLowerCase();
    if (parsed.protocol !== 'https:' || !isTwitterHost(hostname)) {
        throw new ArgumentError(`Invalid tweet URL host: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');
    }
    const match = parsed.pathname.match(TWEET_PATH_PATTERN);
    if (!match?.[1]) {
        throw new ArgumentError(`Could not extract tweet ID from URL: ${value}`, 'Use a full https://x.com/<user>/status/<id> URL');
    }
    return {
        id: match[1],
        url: parsed.toString(),
    };
}

/**
 * Build a JS source fragment that, when embedded inside a `page.evaluate(...)`
 * IIFE, declares browser-side helpers for scoping operations to a specific

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use the full URL including https:// scheme
  2. If you only have the ID, build the URL: `https://x.com/<user>/status/<id>` or `https://x.com/i/status/<id>` if supported
  3. Trim whitespace/newlines from the input before passing

Example fix

// before
opencli twitter retweet 20
// after
opencli twitter retweet https://x.com/jack/status/20
Defensive patterns

Strategy: validation

Validate before calling

function normalizeTweetUrl(v) {
  const s = String(v ?? '').trim();
  if (/^\d+$/.test(s)) return `https://x.com/i/status/${s}`; // bare ID
  if (!/^https:\/\//.test(s)) return `https://${s}`;
  return s;
}
// then verify: new URL(normalizeTweetUrl(v)) does not throw

Type guard

function isParseableUrl(v) { try { new URL(String(v).trim()); return true; } catch { return false; } }

Try / catch

try {
  await opencli.twitter.retweet(url);
} catch (e) {
  if (e.name === 'ArgumentError' && /Invalid tweet URL:/.test(e.message)) {
    console.error('Use https://x.com/<user>/status/<id>');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing 'jack/status/20', 'x.com/jack/status/20' (no scheme is actually parseable by URL only with base — bare host without scheme throws), 'opencli twitter retweet 20' (just the ID), or a URL with stray spaces.

Common situations: Users pasting just the tweet ID or path from the address bar minus scheme, shell mangling, or code passing a tweet object instead of its URL string.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/45a0b97eed00bc2c. Report an issue: GitHub.