withastro/astro · error · AstroError
StaticClientAddressNotAvailable
StaticClientAddressNotAvailable
Error message
`Astro.clientAddress` is only available on pages that are server-rendered.
What it means
Thrown by the clientAddress getter on the APIContext returned from createContext (used in dev/middleware contexts). When no clientAddress was passed to the context, reading it is meaningless, so StaticClientAddressNotAvailable is thrown. Unlike the route-aware getter, this context has no prerender/adapter logic, only a presence check.
Source
Thrown at packages/astro/src/core/middleware/index.ts:110
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 d081033d5f)
Solutions
- Only read clientAddress in contexts where it is provided (server-rendered requests with a supporting adapter).
- Guard with an adapter check or feature flag before reading clientAddress in middleware.
- Fall back to request headers when clientAddress is unavailable.
Example fix
// before
export const onRequest = (ctx, next) => {
log(ctx.clientAddress);
return next();
};
// after
export const onRequest = (ctx, next) => {
log(ctx.clientAddress ?? ctx.request.headers.get('x-forwarded-for'));
return next();
}; Defensive patterns
Strategy: validation
Validate before calling
// In middleware, guard clientAddress access.
export const onRequest = (ctx, next) => {
const ip = ctx.clientAddress ?? ctx.request.headers.get('x-forwarded-for');
return next();
}; Type guard
function hasClientAddress(ctx: { clientAddress?: string }): boolean {
return typeof ctx.clientAddress === 'string' && ctx.clientAddress.length > 0;
} Try / catch
try {
ip = ctx.clientAddress;
} catch (e) {
if (e instanceof Error && /server-rendered/i.test(e.message)) {
ip = ctx.request.headers.get('x-forwarded-for') ?? undefined;
} else throw e;
} Prevention
- Do not assume clientAddress exists in middleware; provide a fallback.
- Skip IP logic in prerendered/static contexts.
- Test middleware with and without an adapter.
When it happens
Trigger: Reading context.clientAddress from middleware or an APIContext that was created without a clientAddress argument (e.g. during dev, tests, or an SSG build). The getter throws when the local clientAddress variable is falsy.
Common situations: Accessing clientAddress inside middleware that also runs during prerender/dev when no address exists; SSR middleware in a static-output project; reading clientAddress before an adapter is configured.
Related errors
- PrerenderClientAddressNotAvailable
- ClientAddressNotAvailable
- StaticClientAddressNotAvailable
- MiddlewareNotAResponse
- MiddlewareNoDataOrNextCalled
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/566597465b1c4a04.
Report an issue: GitHub.