jackwener/OpenCLI · error · ArgumentError

Invalid tweet URL host: ${value}

Error message

Invalid tweet URL host: ${value}

What it means

ArgumentError from parseTweetUrl when the URL parses but its protocol is not https: or its hostname is not a twitter/x.com host (isTwitterHost). Only https://(www.)(x.com|twitter.com) URLs are accepted, so other schemes/hosts are rejected before extracting the tweet ID.

Source

Thrown at clis/twitter/shared.js:61

        || 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
 * tweet by status id. Sibling adapters historically inlined ad-hoc article
 * lookups that either (a) skipped scoping entirely (silent: act on first
 * matching button on a conversation page) or (b) used substring matches like
 * `pathname.includes('/status/' + tweetId)` (silent: `/status/123` matches

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use an https://x.com/<user>/status/<id> URL (or https://twitter.com/... equivalent)
  2. Expand t.co short links to the real x.com status URL first
  3. Change http:// to https:// if the host is otherwise correct

Example fix

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

Strategy: validation

Validate before calling

function isTweetHostUrl(v) {
  try {
    const u = new URL(String(v).trim());
    const okHost = u.hostname === 'x.com' || u.hostname === 'twitter.com' || u.hostname.endsWith('.twitter.com');
    return u.protocol === 'https:' && okHost && /\/status\/\d+/.test(u.pathname);
  } catch { return false; }
}
if (!isTweetHostUrl(url)) throw new Error('expected https://x.com/<user>/status/<id>');

Type guard

function isHttpsTwitterUrl(v) {
  try { const u = new URL(String(v).trim()); return u.protocol === 'https:' && /(^|\.)(x\.com|twitter\.com)$/.test(u.hostname); } catch { return false; }
}

Try / catch

try {
  await opencli.twitter.retweet(url);
} catch (e) {
  if (e.name === 'ArgumentError' && /host/.test(e.message)) {
    console.error('Only https://x.com or https://twitter.com status URLs are supported');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing http:// (not https), mobile.twitter.com variants outside the accepted suffix set, a t.co short link, a facebook/reddit URL, or javascript:/file: URIs.

Common situations: Copying an http:// link from old logs, pasting a shortened t.co URL from a tweet, pointing at a mirror/ninga-style frontend host, or test fixtures with example.com URLs.

Related errors


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