{"record":{"id":"0ec56a42e8229f2b","repo":"vercel/next.js","slug":"url-parameter-is-valid-but-upstream-response-tim","errorCode":null,"errorMessage":"\"url\" parameter is valid but upstream response timed out","messagePattern":"\"url\" parameter is valid but upstream response timed out","errorType":"http","errorClass":"ImageError","httpStatus":504,"severity":"error","filePath":"packages/next/src/server/image-optimizer.ts","lineNumber":894,"sourceCode":"        'upstream image',\n        href,\n        'hostname resolved to private IP',\n        JSON.stringify(privateIps),\n        'If this is expected and you understand SSRF risk, use images.dangerouslyAllowLocalIP = true to continue.'\n      )\n      throw new ImageError(400, '\"url\" parameter is not allowed')\n    }\n  }\n  const res = await fetch(href, {\n    signal: AbortSignal.timeout(7_000),\n    redirect: 'manual',\n  }).catch((err) => err as Error)\n\n  if (res instanceof Error) {\n    const err = res as Error\n    if (err.name === 'TimeoutError') {\n      Log.error('upstream image response timed out for', href)\n      throw new ImageError(\n        504,\n        '\"url\" parameter is valid but upstream response timed out'\n      )\n    }\n    throw err\n  }\n\n  const locationHeader = res.headers.get('Location')\n  if (\n    isRedirect(res.status) &&\n    locationHeader &&\n    URL.canParse(locationHeader, href)\n  ) {\n    if (count === 0) {\n      Log.error('upstream image response had too many redirects', href)\n      throw new ImageError(\n        508,\n        '\"url\" parameter is valid but upstream response is invalid'","sourceCodeStart":876,"sourceCodeEnd":912,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/image-optimizer.ts#L876-L912","documentation":"Thrown by fetchExternalImage (ImageError 504) when fetching the upstream image URL times out. The fetch is wrapped in AbortSignal.timeout(7_000) (7 seconds); if it rejects with a TimeoutError, Next.js logs the href and returns a 504 to the client. This indicates the upstream image host is unreachable or too slow.","triggerScenarios":"fetch(href) with a 7-second abort timeout rejects and err.name === 'TimeoutError'. The catch converts it to ImageError(504, '\"url\" parameter is valid but upstream response timed out').","commonSituations":"Upstream image server is slow or overloaded. Network latency between the Next.js server and the image host. A firewall or egress filter dropping packets so the connection hangs until timeout. Transient upstream outage.","solutions":["Retry the request; timeouts are often transient.","Verify the upstream image URL is reachable from the server (curl with timing from the host).","Self-host/mirror the image locally or via a CDN edge closer to the server.","If you control the timeout, consider caching the optimized image (images.minimumCacheTTL) to avoid repeated upstream fetches."],"exampleFix":"# before\n/_next/image?url=https://slow-host.example/photo.jpg&w=640&q=75  # 504\n\n# after\n# verify reachability and cache; mirror to a faster origin\ncurl -I --max-time 10 https://slow-host.example/photo.jpg\n# then reference a faster/CDN-backed URL","handlingStrategy":"retry","validationCode":"// Probe upstream reachability within the optimizer's timeout before serving\nasync function isUpstreamReachable(href: string, ms = 7000) {\n  const ctrl = new AbortController()\n  const t = setTimeout(() => ctrl.abort(), ms)\n  try {\n    const r = await fetch(href, { method: 'HEAD', signal: ctrl.signal })\n    return r.ok\n  } catch { return false } finally { clearTimeout(t) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Mirror/CDN large images close to the server to avoid timeouts.","Set images.minimumCacheTTL so repeated requests don't re-fetch upstream.","Monitor upstream image host latency and alert on slowdowns."],"tags":["image-optimization","network","timeout","upstream"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}