withastro/astro · error · AstroError
StaticClientAddressNotAvailable
StaticClientAddressNotAvailable
Error message
`Astro.clientAddress` is only available on pages that are server-rendered.
What it means
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.
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
Example fix
// before
export const onRequest = async (context, next) => {
rateLimit(context.clientAddress);
return next();
};
// after
export const onRequest = async (context, next) => {
const ip = context.request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ?? 'unknown';
rateLimit(ip);
return next();
}; Defensive patterns
Strategy: fallback
Validate before calling
function getEdgeClientIp(request: Request): string | null {
return (
request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ??
request.headers.get('x-real-ip')
);
} Try / catch
let ip: string | null;
try {
ip = context.clientAddress;
} catch {
ip = getEdgeClientIp(context.request);
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ClientAddressNotAvailable
- LocalsNotAnObject
- The passed value can't be serialized.
- AdapterSupportOutputMismatch
- `Astro.session` was accessed but no session storage is…
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/566597465b1c4a04.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/middleware/index.ts:131
isPrerendered: false,
get preferredLocale(): string | undefined {
return (preferredLocale ??= computePreferredLocale(request, userDefinedLocales));
},
get preferredLocaleList(): string[] | undefined {
return (preferredLocaleList ??= computePreferredLocaleList(request, userDefinedLocales));
},
get currentLocale(): string | undefined {
return (currentLocale ??= computeCurrentLocale(route, userDefinedLocales, defaultLocale));
},
url,
get originPathname() {
return getOriginPathname(request);
},
get clientAddress() {
if (clientAddress) {
return clientAddress;
}
throw new AstroError(AstroErrorData.StaticClientAddressNotAvailable);
},
get locals() {
if (typeof locals !== 'object') {
throw new AstroError(AstroErrorData.LocalsNotAnObject);
}
return locals;
},
set locals(_) {
throw new AstroError(AstroErrorData.LocalsReassigned);
},
session: undefined,
cache: new DisabledAstroCache(),
csp: undefined,
logger: {
info() {},
warn() {},
error() {},
},View on GitHub (pinned to e294953aa8)