{"record":{"id":"7ce2acb340c123aa","repo":"santifer/career-ops","slug":"a16z-speedrun-talent-invalid-url-url","errorCode":null,"errorMessage":"a16z-speedrun-talent: invalid URL: ${url}","messagePattern":"a16z-speedrun-talent: invalid URL: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"providers/a16z-speedrun-talent.mjs","lineNumber":44,"sourceCode":"const FEED_BASE = 'https://speedrun-talent-network.com/api/v1/jobs';\nconst TRUSTED_HOST = 'speedrun-talent-network.com';\nconst PER_PAGE = 50;\nconst DEFAULT_MAX_PAGES = 6; // × PER_PAGE = the 300-job default scan\n// Runaway bound, not a coverage target: iteration already stops at the\n// feed's reported total_pages (or a short page), so on an honest feed the\n// cap costs nothing and full-board sweeps keep working as the board grows.\n// It only bites a misbehaving feed or an absurd max_pages entry — so it\n// sits well above plausible board size (~353 pages / ~17.6k jobs as of\n// 2026-08), same policy as workday.mjs's cap.\nconst MAX_PAGES_CAP = 1000;\n\n/** @param {string} url */\nfunction assertFeedUrl(url) {\n  let parsed;\n  try {\n    parsed = new URL(url);\n  } catch {\n    throw new Error(`a16z-speedrun-talent: invalid URL: ${url}`);\n  }\n  if (parsed.protocol !== 'https:') throw new Error(`a16z-speedrun-talent: URL must use HTTPS: ${url}`);\n  if (parsed.hostname !== TRUSTED_HOST) {\n    throw new Error(`a16z-speedrun-talent: untrusted hostname \"${parsed.hostname}\" — must be ${TRUSTED_HOST}`);\n  }\n  return url;\n}\n\n/** Resolve the page cap: a positive integer `max_pages` on the entry, capped. */\nfunction resolveMaxPages(entry) {\n  const v = entry?.max_pages;\n  if (Number.isInteger(v) && v > 0) return Math.min(v, MAX_PAGES_CAP);\n  return DEFAULT_MAX_PAGES;\n}\n\n/** Optional server-side query: `q:` on the entry, else joined `keywords:`. */\nfunction resolveQuery(entry) {\n  if (typeof entry?.q === 'string' && entry.q.trim()) return entry.q.trim();","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/santifer/career-ops/blob/9b17a8ac97b398a496b38e423ae24e433b43254f/providers/a16z-speedrun-talent.mjs#L26-L62","documentation":"The a16z-speedrun-talent provider validates its feed URL via assertFeedUrl(). This first guard throws if `new URL(url)` fails — i.e. the URL string is malformed (empty, no protocol, embedded illegal characters). It is the parse step before the protocol and hostname checks.","triggerScenarios":"FEED_BASE (compiled-in feed constant) or a supplied URL fails URL parsing: empty string, 'speedrun.a16z.com/talent' with no scheme, undefined coerced to a string, control characters. Since FEED_BASE is a trusted constant, this most often signals a bad edit to that constant or a malformed test entry.","commonSituations":"FEED_BASE edited to drop the https:// scheme; a copy-paste of a partial URL.","solutions":["Inspect FEED_BASE at the top of providers/a16z-speedrun-talent.mjs — it must be a complete absolute URL (e.g. 'https://speedrun.a16z.com/api/talent').","Ensure any entry URL override is a valid absolute https URL."],"exampleFix":"// before\nconst FEED_BASE = 'speedrun.a16z.com/api/talent';\n\n// after\nconst FEED_BASE = 'https://speedrun.a16z.com/api/talent';","handlingStrategy":"validation","validationCode":"function assertValidUrl(url) {\n  try { new URL(url); return true; } catch { return false; }\n}\nif (!assertValidUrl(FEED_BASE)) throw new Error('a16z FEED_BASE is not a valid URL');","typeGuard":"/** @param {unknown} u @returns {u is string} */\nfunction isValidUrlString(u) {\n  if (typeof u !== 'string' || u.length === 0) return false;\n  try { new URL(u); return true; } catch { return false; }\n}","tryCatchPattern":"try { assertFeedUrl(url); } catch (err) {\n  if (/invalid URL/.test(err.message)) console.error('a16z FEED_BASE malformed — fix it.');\n  throw err;\n}","preventionTips":["Validate feed constants at startup; unit-test that FEED_BASE passes assertFeedUrl.","Keep FEED_BASE/TRUSTED_HOST in config so a host change doesn't require a code edit."],"tags":["a16z","url","validation","provider","ssrf-guard"],"backgroundTag":null,"analyzedSha":"9b17a8ac97b398a496b38e423ae24e433b43254f","analyzedAt":"2026-08-13T00:48:39.135Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}