withastro/astro · error · AstroError
LocalsReassigned
LocalsReassigned
Error message
`locals` cannot be assigned directly.
What it means
The setter for locals on createContext()-built contexts always throws AstroErrorData.LocalsReassigned. As with Astro.locals, the object identity is shared with everything downstream of the context, so it can only be decorated property-by-property, never replaced. This is the same contract enforced on every Astro context variant.
Solutions
- Mutate instead: context.locals.user = user
- To restore many fields: Object.assign(context.locals, parsedLocals)
- Initialize individual fields early in middleware rather than replacing the container
Example fix
// before
const parsed = JSON.parse(request.headers.get('x-astro-locals') ?? '{}');
context.locals = parsed;
// after
const parsed = JSON.parse(request.headers.get('x-astro-locals') ?? '{}');
Object.assign(context.locals, parsed); Defensive patterns
Strategy: validation
Validate before calling
function restoreLocals(context: APIContext, parsed: Record<string, unknown>): void {
Object.assign(context.locals, parsed);
} Prevention
- Mutate context.locals properties; never assign the object
- When restoring forwarded locals, Object.assign into the existing container
- Initialize fields one by one at the top of middleware instead of replacing the container
When it happens
Trigger: `context.locals = {...}` inside middleware running against an adapter-created (e.g. edge-bridged) context; attempting to reassign locals to a fresh object after parsing them off a header.
Common situations: Edge middleware that receives locals from a header and 'restores' them by assignment instead of merging; developers porting code where ctx.state is assignable; initializing locals at the top of middleware with an assignment.
Related errors
- LocalsReassigned
- AstroResponseHeadersReassigned
- `Astro.session` was accessed but no session storage is…
- `context.next` is not implemented for serverless functions
- FetchState not found on APIContext. `next(payload)`…
AI-assisted analysis of withastro/astro@e294953aa8 (2026-08-18).
Data as JSON: /api/errors/0b37ba74e79d13c2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/astro/src/core/middleware/index.ts:140
},
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() {},
},
};
return Object.assign(context, {
getActionResult: createGetActionResult(context.locals),
callAction: createCallAction(context),
});
}
/**
* Checks whether the passed `value` is serializable.View on GitHub (pinned to e294953aa8)