{"record":{"id":"48361f7727fd0b05","repo":"santifer/career-ops","slug":"vc-portfolios-a16z-portfolio-fetch-failed-err","errorCode":null,"errorMessage":"vc-portfolios: a16z portfolio fetch failed — ${err.message}","messagePattern":"vc-portfolios: a16z portfolio fetch failed — (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"seeds/vc-portfolios.mjs","lineNumber":419,"sourceCode":"  return null;\n}\n\n/**\n * Fetch the a16z public portfolio page and return parsed SeedCompany entries.\n *\n * a16z does not expose a public JSON API, so we fetch the HTML portfolio page\n * and parse it with `parseA16zPayload()`.\n *\n * @param {{ timeoutMs?: number }} [opts]\n * @returns {Promise<SeedCompany[]>}\n */\nexport async function fetchA16zCompanies({ timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {\n  let html;\n  try {\n    const res = await fetchWithTimeout(A16Z_PORTFOLIO_URL, { timeoutMs });\n    html = await res.text();\n  } catch (err) {\n    throw new Error(`vc-portfolios: a16z portfolio fetch failed — ${err.message}`);\n  }\n  return parseA16zPayload(html);\n}\n\n// ── SEED_SOURCES registry ────────────────────────────────────────────\n\n/**\n * Registry mapping seed source names to their fetch functions.\n * Consumed by scan-ats-full.mjs --seeds flag and CLI tooling.\n *\n * To add a new VC portfolio:\n *  1. Add a fetchXyzCompanies() function above.\n *  2. Add an entry here: { fetch: fetchXyzCompanies, label: 'XYZ Portfolio' }\n *\n * @type {Record<string, { fetch: (opts?: object) => Promise<SeedCompany[]>, label: string }>}\n */\nexport const SEED_SOURCES = {\n  yc: {","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/santifer/career-ops/blob/1696bec4d021768e7359f9aad6b329cba883da20/seeds/vc-portfolios.mjs#L401-L437","documentation":"fetchA16zCompanies downloads the a16z portfolio HTML page via fetchWithTimeout and re-throws any fetch failure as 'vc-portfolios: a16z portfolio fetch failed — <cause>'. Unlike the YC fetcher, there is no partial-data fallback: any network or HTTP error is fatal for this source. Parsing failures (parseA16zPayload) are NOT caught here — only the fetch itself.","triggerScenarios":"Calling fetchA16zCompanies when https://a16z.com/portfolio (A16Z_PORTFOLIO_URL) returns a non-2xx status via fetchWithTimeout (403 from bot protection, 404 after a site redesign, 5xx outage), or the request times out / DNS fails.","commonSituations":"a16z.com serving a Cloudflare challenge page to non-browser clients (403); the portfolio URL changed when a16z redesigned their site; corporate firewall blocks the domain; timeout hit because the page is large and the connection is slow.","solutions":["Test A16Z_PORTFOLIO_URL with curl -I to see the actual status; if 403/Cloudflare, the endpoint needs a browser-like User-Agent or a headless-browser fetch","Verify the portfolio page still exists after a site redesign and update A16Z_PORTFOLIO_URL to the new URL","Increase timeoutMs if the failure is a timeout on a slow connection","Check the inner err.message — timeouts, DNS failures (ENOTFOUND) and HTTP statuses each need different fixes (network/VPN vs URL update vs backoff)"],"exampleFix":"// before\nconst res = await fetchWithTimeout(A16Z_PORTFOLIO_URL, { timeoutMs });\n// Error: vc-portfolios: a16z portfolio fetch failed — HTTP 403: ...Just a moment...\n// after: allow configuring a browser-like UA / longer timeout\nconst res = await fetchWithTimeout(A16Z_PORTFOLIO_URL, { timeoutMs: 30000, headers: { 'user-agent': 'Mozilla/5.0 (compatible; seed-fetcher)' } });","handlingStrategy":"fallback","validationCode":"const status = await fetch(A16Z_PORTFOLIO_URL, { method: 'HEAD' })\n  .then(r => r.status).catch(() => 0);\nif (status !== 200) console.warn(`a16z portfolio URL unhealthy (HTTP ${status}) — expect fetch failure`);","typeGuard":null,"tryCatchPattern":"let companies;\ntry {\n  companies = await fetchA16zCompanies({ timeoutMs });\n} catch (err) {\n  console.warn(`${err.message}; using cached a16z portfolio`);\n  companies = loadCachedA16z() ?? [];\n}","preventionTips":["Keep a cached copy of the last successful portfolio parse for fallback","Re-verify A16Z_PORTFOLIO_URL after any site redesign; treat 403 as bot-protection and use a browser-like UA or headless browser","Set timeoutMs generously for large pages","Skip the a16z source gracefully instead of failing the whole seed run"],"tags":["http","network","scraping","bot-protection"],"backgroundTag":"http-non-2xx-response","analyzedSha":"1696bec4d021768e7359f9aad6b329cba883da20","analyzedAt":"2026-09-01T19:19:23.111Z","contentChangedAt":"2026-09-01T19:19:23.111Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}