CORRECT008 · Browser global in server module code
Severity: critical · Category: correctness
What it checks
Section titled “What it checks”Flags reads of browser-only globals (window, document, localStorage, sessionStorage, navigator, location, history, screen, matchMedia, requestAnimationFrame, cancelAnimationFrame, IntersectionObserver, ResizeObserver, MutationObserver, alert, confirm, prompt) in code that always runs on the server:
- module scope of a
.svelte.ts/.svelte.jsrunes module or a.svelte<script module>block (crashes when the module is imported on the server), and - SvelteKit route/hooks files — top level,
load/action/endpoint handler bodies, and theinithook (crashes at import or on every request).
Not flagged: code guarded by browser from $app/environment (aliases included) or a typeof window !== 'undefined' check (early-return guards included); code inside onMount/$effect/ordinary functions (they don’t run at module evaluation); a bare typeof window (never throws); names you imported or declared yourself (const document = …); closures nested inside handlers (typically client callbacks); and files that export ssr = false themselves.
Why it matters
Section titled “Why it matters”None of these globals exist in Node. A module-scope window read crashes the server the moment the file is imported; in a load it crashes every SSR request — ReferenceError: window is not defined, a production 500 the compiler never warns about.
How to fix
Section titled “How to fix”export function load() { const stored = localStorage.getItem('filters'); // ❌ ReferenceError on the server
return {};}Move the browser access to the client side:
<script> let stored = $state(null); $effect(() => { stored = localStorage.getItem('filters'); // ✅ effects never run on the server });</script>Or guard it explicitly:
import { browser } from '$app/environment';
const stored = browser ? localStorage.getItem('filters') : null; // ✅