{"record":{"id":"566597465b1c4a04","repo":"withastro/astro","slug":"staticclientaddressnotavailable-566597","errorCode":"StaticClientAddressNotAvailable","errorMessage":"`Astro.clientAddress` is only available on pages that are server-rendered.","messagePattern":"`Astro\\.clientAddress` is only available on pages that are server-rendered\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/core/middleware/index.ts","lineNumber":131,"sourceCode":"\t\tisPrerendered: false,\n\t\tget preferredLocale(): string | undefined {\n\t\t\treturn (preferredLocale ??= computePreferredLocale(request, userDefinedLocales));\n\t\t},\n\t\tget preferredLocaleList(): string[] | undefined {\n\t\t\treturn (preferredLocaleList ??= computePreferredLocaleList(request, userDefinedLocales));\n\t\t},\n\t\tget currentLocale(): string | undefined {\n\t\t\treturn (currentLocale ??= computeCurrentLocale(route, userDefinedLocales, defaultLocale));\n\t\t},\n\t\turl,\n\t\tget originPathname() {\n\t\t\treturn getOriginPathname(request);\n\t\t},\n\t\tget clientAddress() {\n\t\t\tif (clientAddress) {\n\t\t\t\treturn clientAddress;\n\t\t\t}\n\t\t\tthrow new AstroError(AstroErrorData.StaticClientAddressNotAvailable);\n\t\t},\n\t\tget locals() {\n\t\t\tif (typeof locals !== 'object') {\n\t\t\t\tthrow new AstroError(AstroErrorData.LocalsNotAnObject);\n\t\t\t}\n\t\t\treturn locals;\n\t\t},\n\t\tset locals(_) {\n\t\t\tthrow new AstroError(AstroErrorData.LocalsReassigned);\n\t\t},\n\t\tsession: undefined,\n\t\tcache: new DisabledAstroCache(),\n\t\tcsp: undefined,\n\t\tlogger: {\n\t\t\tinfo() {},\n\t\t\twarn() {},\n\t\t\terror() {},\n\t\t},","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/withastro/astro/blob/e294953aa8aadd98d5be92e60a03037b05dbdfd4/packages/astro/src/core/middleware/index.ts#L113-L149","documentation":"createContext() (core middleware context factory, used by adapters such as Vercel and Netlify to bridge edge middleware) only exposes clientAddress when the platform passed one in — the docs on the option say it must come from a trusted source. The getter throws AstroErrorData.StaticClientAddressNotAvailable when no value was supplied, because the standalone context has no other way to know the client IP.","triggerScenarios":"Reading context.clientAddress inside middleware that runs against an adapter-created context (Vercel/Netlify edge middleware bridging) where createContext was called without a clientAddress argument; the same middleware code working in the serverless function but throwing at the edge.","commonSituations":"Geolocation or rate-limiting middleware promoted from functions to edge middleware; adapters that have not wired clientAddress through their edge entry; local tests calling createContext({ request }) without an address.","solutions":["Read the IP from platform headers instead: context.request.headers.get('x-forwarded-for') or x-real-ip","Adapter authors: pass the platform-provided trusted address into createContext({ clientAddress })","Use the platform's own geolocation API for edge middleware instead of clientAddress"],"exampleFix":"// before\nexport const onRequest = async (context, next) => {\n  rateLimit(context.clientAddress);\n  return next();\n};\n\n// after\nexport const onRequest = async (context, next) => {\n  const ip = context.request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ?? 'unknown';\n  rateLimit(ip);\n  return next();\n};","handlingStrategy":"fallback","validationCode":"function getEdgeClientIp(request: Request): string | null {\n  return (\n    request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ??\n    request.headers.get('x-real-ip')\n  );\n}","typeGuard":null,"tryCatchPattern":"let ip: string | null;\ntry {\n  ip = context.clientAddress;\n} catch {\n  ip = getEdgeClientIp(context.request);\n}","preventionTips":["In edge middleware, read the IP from platform headers or the platform geo API instead of clientAddress","Adapter authors: pass a trusted clientAddress into createContext when the platform provides one","Keep IP access behind one helper shared by edge and function code paths"],"tags":["client-address","edge-middleware","adapter","create-context"],"backgroundTag":"client-address-unavailable","analyzedSha":"e294953aa8aadd98d5be92e60a03037b05dbdfd4","analyzedAt":"2026-08-18T18:48:03.901Z","contentChangedAt":"2026-08-18T18:48:03.901Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}