jackwener/OpenCLI · error · ArgumentError

match must be an HLTV match, stats series, or mapstats URL

Error message

match must be an HLTV match, stats series, or mapstats URL

What it means

This ArgumentError is thrown by normalizeMatchUrl when the value is non-empty and parses as a URL, but the pathname does not match an accepted HLTV match path: /matches/<digits>/, /stats/matches/<digits>/, or /stats/matches/mapstatsid/<digits>/. The library only supports those three match URL shapes; other HLTV pages (player, team, event, results listing) are rejected so downstream match-id extraction never sees garbage.

Source

Thrown at clis/hltv/utils.js:465

  const shortMatch = raw.match(/^(\d{2})\/(\d{2})\/(\d{2})$/);
  if (shortMatch) {
    const [, dd, mm, yy] = shortMatch;
    return `20${yy}-${mm}-${dd}`;
  }
  const longMatch = raw.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
  if (longMatch) {
    const [, dd, mm, yyyy] = longMatch;
    return `${yyyy}-${mm}-${dd}`;
  }
  return raw;
}

export function normalizeMatchUrl(value) {
  const raw = String(value ?? '').trim();
  if (!raw) throw new ArgumentError('match is required');
  const url = /^https?:\/\//i.test(raw) ? parseHltvUserUrl(raw, 'match') : new URL(raw.replace(/^\/+/, ''), `${BASE}/`);
  if (!/^\/(?:matches\/\d+\/|stats\/matches\/(?:mapstatsid\/)?\d+\/)/.test(url.pathname)) {
    throw new ArgumentError('match must be an HLTV match, stats series, or mapstats URL');
  }
  return url;
}

function buildPerformanceUrl(mapstatsUrl) {
  const url = new URL(mapstatsUrl, BASE);
  url.pathname = url.pathname.replace('/stats/matches/mapstatsid/', '/stats/matches/performance/mapstatsid/');
  return url;
}

export async function resolveMatchMapUrls(page, match) {
  const url = normalizeMatchUrl(match);
  if (/^\/stats\/matches\/mapstatsid\/\d+\//.test(url.pathname)) return [url.toString()];

  await gotoAndWait(page, url, 'a[href*="/stats/matches/mapstatsid/"]', 'hltv match map link page');
  const links = await page.evaluate((payload) => {
    const seen = new Set();
    const out = [];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use a full match URL: https://www.hltv.org/matches/<id>/<slug>, /stats/matches/<id>/<slug>, or /stats/matches/mapstatsid/<id>/<slug>.
  2. Extract the specific match page link from a results page instead of passing the listing URL.
  3. Verify the pathname starts with /matches/<digits>/ or /stats/matches/ and includes the numeric id.
  4. If you have only a match id, construct the URL yourself, e.g. new URL(`/matches/${id}/x/`, BASE) form: `https://www.hltv.org/matches/${id}/` + any slug.

Example fix

// before
normalizeMatchUrl('https://www.hltv.org/results'); // ArgumentError
// after
normalizeMatchUrl('https://www.hltv.org/matches/2380210/falcons-vs-vital-iem-cologne-2025');
Defensive patterns

Strategy: type-guard

Validate before calling

function isMatchUrlShape(v) {
  const raw = String(v ?? '').trim();
  if (!raw) return false;
  let pathname = raw;
  if (/^https?:\/\//i.test(raw)) {
    try { pathname = new URL(raw).pathname; } catch { return false; }
  }
  return /^\/(?:matches\/\d+\/|stats\/matches\/(?:mapstatsid\/)?\d+\/)/.test(pathname);
}
if (!isMatchUrlShape(input)) throw new TypeError('not an HLTV match/stats/mapstats URL');

Type guard

function isHltvMatchUrl(v) {
  if (typeof v !== 'string') return false;
  const p = v.replace(/^https?:\/\/[^/]+/i, '');
  return /^\/(?:matches\/\d+\/|stats\/matches\/(?:mapstatsid\/)?\d+\/)/.test(p);
}

Try / catch

try {
  return normalizeMatchUrl(input);
} catch (err) {
  if (err.name === 'ArgumentError' && err.message.startsWith('match must be')) {
    throw new Error(`"${input}" is not a match/stats-series/mapstats URL`, { cause: err });
  }
  throw err;
}

Prevention

When it happens

Trigger: normalizeMatchUrl('https://www.hltv.org/team/6667/falcons'), normalizeMatchUrl('/results'), normalizeMatchUrl('https://www.hltv.org/player/3741/niko'), or a match URL without a trailing slash/id segment pattern, e.g. '/matches' or '/matches/abc/label'.

Common situations: Pasting a results-list or news URL instead of a specific match page; mixing up team/player and match URLs; using a localized or redesigned HLTV path; passing stats URLs for team/player stats rather than series/mapstats.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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