You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
theme: ctx.theme in a handler bakes the first visitor's theme into a shared PPR shell or cache() entry #971
ctx.theme read in a route handler bakes the first visitor's theme into a shared PPR shell or route cache() entry. Nothing refuses or warns. cookies() in the same place is guarded: it refuses the capture, and under cache() it throws.
Served with cookie: theme=dark, then theme=light (through serveShellRequest):
miss.shellStatus MISS entry.initialTheme dark
hit.shellStatus HIT hit.prelude has [ 'theme-is-dark' ] refused warnings []
Under cache({ ttl: 300 }) with no ppr, the second visitor also gets theme-is-dark. The cookies() control is refused under ppr and returns 500 under cache().
The <html> class is still correct, because the inline theme script reads document.cookie before paint. But handler output derived from ctx.theme shows the capturing visitor's theme to everyone until the entry expires. The theme skill's own example, <SettingsPage theme={ctx.theme} /> (skills/theme/SKILL.md:93-95), hits this.
Cause
src/router/handler-context.ts:299 copies the value with theme: requestContext?.theme.
getTheme() / effectiveCookie in src/server/request-context.ts (~1140-1162) read the theme cookie without assertNotInsideCacheContext or assertNotInsideShellCapture. src/server/cookie-store.ts:64-65 applies both guards to cookies().
The same output reproduces on main f24d459 and on v0.17.0.
Proposed fix
Make the handler ctx's theme a getter that runs the same two guards as cookies(). A capture then refuses, and a cache() miss throws.
Keep the router's internal reqCtx.theme read unguarded (initialTheme).
Note in skills/theme to read the theme with useTheme() in a client component, or in a live loader, on ppr/cache() routes.
Activity
fix(router): ctx.theme read in a handler refuses a PPR capture and th…
fix(router): ctx.theme read in a handler refuses a PPR capture and th…