jackwener/OpenCLI · error · ArgumentError

invalid xiaoe URL: ${raw}

Error message

invalid xiaoe URL: ${raw}

What it means

requireXiaoePageUrl attempts new URL(raw) on the supplied value; when the string is not a parseable absolute URL it throws ArgumentError('invalid xiaoe URL: <raw>') with an example of the expected format.

Source

Thrown at clis/xiaoe/content.js:89

        const src = imgs[i].getAttribute('src') || imgs[i].src || '';
        if (!src) continue;
        if (src.startsWith('data:')) continue;
        if (!src.includes('xiaoe')) continue;
        count += 1;
    }
    return count;
}

export function requireXiaoePageUrl(value, commandName) {
    const raw = typeof value === 'string' ? value.trim() : '';
    if (!raw) {
        throw new ArgumentError('url is required (positional)');
    }
    let parsed;
    try {
        parsed = new URL(raw);
    } catch {
        throw new ArgumentError(
            `invalid xiaoe URL: ${raw}`,
            `Example: opencli xiaoe ${commandName} https://appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx`,
        );
    }
    if (parsed.protocol !== 'https:') {
        throw new ArgumentError(
            `xiaoe URL must use https (got ${parsed.protocol.replace(':', '')})`,
            `Example: opencli xiaoe ${commandName} https://appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx`,
        );
    }
    const host = parsed.hostname.toLowerCase();
    if (host !== 'h5.xet.citv.cn' && !host.endsWith('.h5.xet.citv.cn')) {
        throw new ArgumentError(
            `url must be on h5.xet.citv.cn or a shop subdomain (got ${parsed.hostname})`,
            `Example: opencli xiaoe ${commandName} https://appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx`,
        );
    }
    return parsed.toString();

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Include the full scheme: https://appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx.
  2. Quote the URL in the shell so ?, &, and # are not interpreted.
  3. Trim whitespace and remove any surrounding text before pasting.
  4. Validate in JS beforehand with new URL(value) inside try/catch.

Example fix

// before
opencli xiaoe content appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx
// after
opencli xiaoe content 'https://appxxxx.h5.xet.citv.cn/p/course/ecourse/v_xxxxx'
Defensive patterns

Strategy: validation

Validate before calling

function assertHttpsUrl(raw) {
  let u;
  try { u = new URL(String(raw).trim()); } catch { throw new Error(`invalid xiaoe URL: ${raw}`); }
  if (u.protocol !== 'https:') throw new Error('must use https');
  return u;
}

Type guard

const isAbsoluteHttpUrl = v => { try { const u = new URL(v); return u.protocol === 'https:' || u.protocol === 'http:'; } catch { return false; } };

Try / catch

try {
  await contentCommand(url);
} catch (e) {
  if (e instanceof ArgumentError && /invalid xiaoe URL/.test(e.message)) {
    console.error('Include the full https:// scheme and quote the URL.');
    process.exit(2);
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a relative path ('/p/course/...'), a bare host ('appxxxx.h5.xet.citv.cn'), a malformed URL, or a value with stray whitespace/characters so the URL constructor throws.

Common situations: Copy-paste truncated the 'https://' prefix; shell mangled query strings (?, &) that weren't quoted; pasted a URL with surrounding text or trailing punctuation; passed an app-specific deep link that isn't an HTTP URL.

Related errors


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