{"record":{"id":"20e9ee60c68e9c3c","repo":"vercel/next.js","slug":"failed-to-fetch-url","errorCode":null,"errorMessage":"Failed to fetch ${url}","messagePattern":"Failed to fetch (.+?)","errorType":"exception","errorClass":"NetworkError","httpStatus":null,"severity":"error","filePath":"apps/bundle-analyzer/lib/utils.ts","lineNumber":16,"sourceCode":"import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\nimport { SpecialModule } from './types'\nimport { NetworkError } from './errors'\nimport { AnalyzeData, SourceIndex } from './analyze-data'\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n\nexport async function fetchStrict(url: string): Promise<Response> {\n  let res: Response\n  try {\n    res = await fetch(url)\n  } catch (err) {\n    throw new NetworkError(`Failed to fetch ${url}`, { cause: err })\n  }\n\n  if (!res.ok) {\n    throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`)\n  }\n  return res\n}\n\nexport async function jsonFetcher<T>(url: string): Promise<T> {\n  const res = await fetchStrict(url)\n  return res.json() as Promise<T>\n}\n\nexport function getSpecialModuleType(\n  analyzeData: AnalyzeData | undefined,\n  sourceIndex: SourceIndex | null\n): SpecialModule | null {\n  if (!analyzeData || sourceIndex == null) return null","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/apps/bundle-analyzer/lib/utils.ts#L1-L34","documentation":"Thrown by fetchStrict (utils.ts:11) when the underlying fetch() rejects, wrapped as a NetworkError with the original error preserved as cause. It means the request never got an HTTP response at all — a transport/DNS/connection failure, not a server-returned error. bundle-analyzer uses fetchStrict/jsonFetcher to load its analyze report and other assets over HTTP, so this fires before any status code is seen.","triggerScenarios":"Calling fetchStrict(url) or jsonFetcher(url) where fetch throws: the dev server is not running, the host is unresolvable, the connection is refused/reset, TLS handshake fails, the URL is malformed, or a browser CORS/credential policy blocks the request. Also when the user is offline or behind a proxy that drops the host.","commonSituations":"Opening the bundle-analyzer UI before `next dev`/the report server is ready; pointing the UI at a host/port that doesn't exist; corporate proxy or VPN blocking localhost; mixed content (http fetch from https page); an old report URL left in a bookmark after the server moved.","solutions":["Verify the dev/report server is running and reachable: curl or open the URL directly in a browser tab.","Check the URL scheme/host/port — typos and stale ports are the usual cause; localhost vs 127.0.0.1 vs 0.0.0.0 binding matters.","Inspect err.cause (NetworkError preserves it) for the real transport error (ENOTFOUND, ECONNREFUSED, certificate error) and fix that.","If behind a proxy/VPN, ensure it allows the target host, or serve the report from the same origin to avoid CORS."],"exampleFix":"// before\nconst data = await jsonFetcher<AnalyzeData>(`http://localhost:3000/analyze/report.json`)\n\n// after\ntry {\n  const data = await jsonFetcher<AnalyzeData>(url)\n} catch (err) {\n  if (err instanceof NetworkError) {\n    showUser(`Could not reach ${url}: ${err.cause?.message ?? err.message}. Is the report server running?`)\n    return\n  }\n  throw err\n}","handlingStrategy":"try-catch","validationCode":"function isReachable(url: string): boolean {\n  try { new URL(url); return true } catch { return false }\n}\n// call before fetchStrict:\nif (!isReachable(url)) throw new Error(`Invalid URL: ${url}`)","typeGuard":"import { NetworkError } from './errors'\n\nfunction isNetworkError(err: unknown): err is NetworkError {\n  return err instanceof NetworkError || (err instanceof Error && err.name === 'NetworkError')\n}","tryCatchPattern":"try {\n  return await jsonFetcher<T>(url)\n} catch (err) {\n  if (isNetworkError(err)) {\n    // transport-level: prompt user to start/check the report server\n    throw new Error(`Cannot reach report server at ${url}: ${err.cause?.message ?? err.message}`)\n  }\n  throw err // a 4xx/5xx (error [2]) or other Error — handle separately\n}","preventionTips":["Distinguish NetworkError (transport, this error) from the non-2xx Error (error [2]) by name/instance.","Pre-flight the URL with a cheap HEAD or a socket connect before offering it in the UI.","Keep the report server and analyzer on the same origin to avoid CORS.","Surface err.cause to the user — ENOTFOUND vs ECONNREFUSED vs CERT_HAS_EXPIRED point to very different fixes."],"tags":["network","fetch","bundle-analyzer","connection-refused","cors"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}