{"record":{"id":"0b37ba74e79d13c2","repo":"withastro/astro","slug":"localsreassigned-0b37ba","errorCode":"LocalsReassigned","errorMessage":"`locals` cannot be assigned directly.","messagePattern":"`locals` cannot be assigned directly\\.","errorType":"exception","errorClass":"AstroError","httpStatus":null,"severity":"error","filePath":"packages/astro/src/core/middleware/index.ts","lineNumber":119,"sourceCode":"\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},\n\t};\n\treturn Object.assign(context, {\n\t\tgetActionResult: createGetActionResult(context.locals),\n\t\tcallAction: createCallAction(context),\n\t});\n}\n\n/**\n * Checks whether the passed `value` is serializable.","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/withastro/astro/blob/d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca/packages/astro/src/core/middleware/index.ts#L101-L137","documentation":"Thrown by the locals setter on the APIContext from createContext. As with the Astro global setter, reassigning context.locals wholesale is forbidden; the shared reference must be preserved so middleware and pages see the same object.","triggerScenarios":"Writing `context.locals = { ... }` inside middleware. The setter `set locals(_)` in createContext throws LocalsReassigned unconditionally.","commonSituations":"Middleware that tries to reset locals per request by reassigning; refactored code that replaces the locals object; copy-pasted examples that assign locals.","solutions":["Mutate in place: `context.locals.user = user`.","If you need a clean shape, delete keys individually instead of replacing the object.","Initialize locals fields in the first middleware via property assignment."],"exampleFix":"// before\nexport const onRequest = (ctx, next) => {\n  ctx.locals = { startTime: Date.now() };\n  return next();\n};\n\n// after\nexport const onRequest = (ctx, next) => {\n  ctx.locals.startTime = Date.now();\n  return next();\n};","handlingStrategy":"validation","validationCode":"// Mutate locals; never reassign in middleware.\nexport const onRequest = (ctx, next) => {\n  ctx.locals.startTime = Date.now();\n  return next();\n};","typeGuard":"function assertLocalsMutable(locals: unknown): asserts locals is Record<string, unknown> {\n  if (typeof locals !== 'object' || locals === null) throw new Error('locals must be object');\n}","tryCatchPattern":"try {\n  ctx.locals.x = 1;\n} catch (e) {\n  if (e instanceof Error && /cannot be assigned directly/i.test(e.message)) {\n    // reassignment detected; switch to property mutation\n  }\n  throw e;\n}","preventionTips":["Use `context.locals.key = value`, never `context.locals = {...}`.","Lint against `locals =` in middleware files.","Reset locals by deleting keys, not replacing the object."],"tags":["locals","middleware","context","state"],"backgroundTag":null,"analyzedSha":"d081033d5fe8e8a68c4bbbad4af9d2deb9c74bca","analyzedAt":"2026-08-12T13:37:29.035Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}