{"record":{"id":"c3d20589db9d0bdf","repo":"jackwener/OpenCLI","slug":"series-resolution-requires-a-stats-matches-mapsta","errorCode":null,"errorMessage":"series resolution requires a /stats/matches/mapstatsid/:id/:slug URL","messagePattern":"series resolution requires a /stats/matches/mapstatsid/:id/:slug URL","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/hltv/utils.js","lineNumber":501,"sourceCode":"    const out = [];\n    for (const a of document.querySelectorAll('a[href*=\"/stats/matches/mapstatsid/\"]')) {\n      const href = new URL(a.getAttribute('href'), payload.base);\n      href.search = '';\n      href.hash = '';\n      const key = href.pathname.match(/mapstatsid\\/(\\d+)\\//)?.[1];\n      if (!key || seen.has(key)) continue;\n      seen.add(key);\n      out.push(href.toString());\n    }\n    return out;\n  }, { base: BASE });\n  return assertRows(links, 'hltv match map urls');\n}\n\nexport async function resolveStatsSeriesUrlFromMap(page, mapstatsUrl) {\n  const url = normalizeMatchUrl(mapstatsUrl);\n  if (!/^\\/stats\\/matches\\/mapstatsid\\/\\d+\\//.test(url.pathname)) {\n    throw new ArgumentError('series resolution requires a /stats/matches/mapstatsid/:id/:slug URL');\n  }\n\n  await gotoAndWait(page, url, 'a[href*=\"/stats/matches/\"]', 'hltv match series link page');\n  const seriesUrl = await page.evaluate((payload) => {\n    for (const a of document.querySelectorAll('a[href*=\"/stats/matches/\"]')) {\n      const href = new URL(a.getAttribute('href'), payload.base);\n      href.search = '';\n      href.hash = '';\n      if (/^\\/stats\\/matches\\/\\d+\\//.test(href.pathname)) return href.toString();\n    }\n    return null;\n  }, { base: BASE });\n\n  return seriesUrl ?? url.toString();\n}\n\nexport async function readMatchMap(page, match) {\n  const url = normalizeMatchUrl(match);","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hltv/utils.js#L483-L519","documentation":"resolveStatsSeriesUrlFromMap() only accepts HLTV map-stats URLs of the form /stats/matches/mapstatsid/:id/:slug. Before doing anything it normalizes the input and tests url.pathname against that regex; if it does not match it throws ArgumentError. This is a fail-fast guard because series resolution navigates to a map-stats page and scrapes the series link, which is meaningless for other URL shapes.","triggerScenarios":"Calling resolveStatsSeriesUrlFromMap(page, mapstatsUrl) with a match-page URL (/stats/matches/:id/:slug), a player/event stats URL, a bare mapstatsid like 'https://www.hltv.org/stats/matches/mapstatsid/73681' without a trailing slash + slug, or any arbitrary string normalizeMatchUrl accepts.","commonSituations":"Passing a full match URL instead of a per-map stats URL (e.g. output of a match listing rather than resolveMatchMapUrls); constructing the URL by hand and omitting the trailing '/'; older HLTV URL formats or redirects that dropped the slug and trailing slash.","solutions":["Resolve the correct map-stats URL first (e.g. via the function that returns 'hltv match map urls' / mapstatsid links) and pass that in","Ensure the URL path ends with a trailing slash after the numeric mapstatsid followed by a slug","Inspect the input string before calling; log it and confirm it matches /^\\/stats\\/matches\\/mapstatsid\\/\\d+\\//"],"exampleFix":"// before\nawait resolveStatsSeriesUrlFromMap(page, 'https://www.hltv.org/matches/2368101/natus-vincere-vs-faZe');\n// after\nawait resolveStatsSeriesUrlFromMap(page, 'https://www.hltv.org/stats/matches/mapstatsid/73681/natus-vincere-vs-faze-map1');","handlingStrategy":"validation","validationCode":"function isMapStatsUrl(input) {\n  const u = new URL(input, 'https://www.hltv.org');\n  return /^\\/stats\\/matches\\/mapstatsid\\/\\d+\\//.test(u.pathname);\n}\nif (!isMapStatsUrl(mapstatsUrl)) throw new Error('expected a /stats/matches/mapstatsid/:id/:slug URL');\nawait resolveStatsSeriesUrlFromMap(page, mapstatsUrl);","typeGuard":"function isMapStatsUrl(v) {\n  try {\n    const u = new URL(String(v), 'https://www.hltv.org');\n    return /^\\/stats\\/matches\\/mapstatsid\\/\\d+\\//.test(u.pathname);\n  } catch { return false; }\n}","tryCatchPattern":"try {\n  const seriesUrl = await resolveStatsSeriesUrlFromMap(page, mapstatsUrl);\n} catch (err) {\n  if (err instanceof ArgumentError && /series resolution requires/.test(err.message)) {\n    console.error('Bad mapstats URL:', mapstatsUrl);\n  } else throw err;\n}","preventionTips":["Always source mapstatsid URLs from the library's own map-URL listing helpers","Keep the trailing slash and slug in the URL path","Add a preflight regex check on any URL you construct by hand"],"tags":["hltv","argument-validation","url-format"],"backgroundTag":"invalid-url-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}