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
- Use a full match URL: https://www.hltv.org/matches/<id>/<slug>, /stats/matches/<id>/<slug>, or /stats/matches/mapstatsid/<id>/<slug>.
- Extract the specific match page link from a results page instead of passing the listing URL.
- Verify the pathname starts with /matches/<digits>/ or /stats/matches/ and includes the numeric id.
- 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
- Keep the library's pathname regex mirrored in your own input validation.
- When extracting links from result pages, filter to /matches/<digits>/ hrefs only.
- Distinguish match URLs from team/player/event URLs at the data-model level.
- Test with all three accepted shapes (matches, stats/matches, mapstatsid) in CI.
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
- player must be like 3741/niko, a player URL, or a stats play
- '${rawInput}' does not look like an autohome series id (a nu
- bilibili follow target must be a valid space.bilibili.com/<u
- chatgpt project commands require a chatgpt.com project id or
- Invalid Chess.com game URL: "${value}" Expected https://www.
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/de1065cf52570a5d.
Report an issue: GitHub.