{"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":45,"sourceCode":"const 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, when the feed omits it, a short page), so\n// on an honest feed the cap costs nothing and full-board sweeps keep working\n// 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":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/providers/a16z-speedrun-talent.mjs#L27-L63","documentation":"assertFeedUrl in providers/a16z-speedrun-talent.mjs throws this when the given URL cannot be parsed by the URL constructor at all (malformed URL syntax). The provider validates every feed URL before fetching, so syntactically broken URLs are rejected with the original string embedded in the message. This is the first of three checks: parse, then HTTPS, then trusted hostname.","triggerScenarios":"Passing a URL string that new URL() rejects — missing scheme ('a16z.com/feed'), spaces or illegal characters, an empty string, or a config value that was never a URL (e.g. a path like '/feed' or a placeholder).","commonSituations":"portals.yml entry with a relative URL or missing https://; whitespace/newline from YAML folding; template placeholder left unsubstituted; env var not set so the URL interpolates to 'undefined/feed'.","solutions":["Fix the URL string so it is a valid absolute URL, e.g. prepend https:// if the scheme is missing.","Trim whitespace/newlines that YAML folding or copying may have introduced.","Check the config source for an unset variable/placeholder interpolating into the URL.","Test with `new URL(url)` in a REPL to see the exact parse failure before retrying."],"exampleFix":"// before\nfetchSpeedrunFeed(config.feedHost + '/api/jobs') // 'example.com/api/jobs' — no scheme\n// after\nfetchSpeedrunFeed('https://example.com/api/jobs')","handlingStrategy":"validation","validationCode":"let parsed;\ntry { parsed = new URL(rawUrl); }\ncatch { throw new Error(`invalid feed URL: ${rawUrl}`); }\nif (parsed.protocol !== 'https:') throw new Error('feed URL must be https');","typeGuard":"function isParsableUrl(s) {\n  try { new URL(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  await fetchSpeedrunFeed(url);\n} catch (e) {\n  if (String(e.message).startsWith('a16z-speedrun-talent: invalid URL')) {\n    console.error(`Malformed feed URL in config: ${url}`);\n    return null;\n  } else throw e;\n}","preventionTips":["Always store feed URLs as full absolute https:// URLs in config.","Trim YAML-folded strings and check for placeholder leftovers at startup.","Validate every configured URL with new URL() during config load, before the provider runs.","Avoid building URLs by string concatenation of unvalidated parts."],"tags":["url-validation","provider","configuration"],"backgroundTag":"invalid-url-format","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}