Skip to content
Latchkey

SvelteKit "ReferenceError: window is not defined" during SSR in CI

SvelteKit renders components on the server first. Code that touches window, document, or localStorage at module load or during render runs in Node, where those globals do not exist, so it throws during the build or prerender.

What this error means

A build, prerender, or SSR test fails with "ReferenceError: window is not defined", with a stack pointing into a component or a library it imports.

node
ReferenceError: window is not defined
    at /src/lib/analytics.js:1:1
    at async render (@sveltejs/kit/src/runtime/server/...)

Common causes

Browser API accessed at module top level

A statement like const w = window.innerWidth runs when the module is imported on the server, before any onMount, so SSR crashes.

A dependency assumes a browser environment

A third-party library reads window/document on import; when bundled into the server build it throws during render.

How to fix it

Guard browser code so it runs only in the browser

  1. Move window/document access into onMount, which runs only on the client.
  2. Or gate it on SvelteKit's browser flag.
  3. Re-run the build or prerender.
Component.svelte
import { browser } from '$app/environment';
import { onMount } from 'svelte';
onMount(() => { if (browser) console.log(window.innerWidth); });

Import a browser-only dependency lazily

Dynamically import a library that needs window inside onMount so it is never loaded on the server.

Component.svelte
onMount(async () => {
  const { default: chart } = await import('browser-only-lib');
});

How to prevent it

  • Never read window/document at module scope in SSR apps.
  • Use the browser guard or onMount for client-only code.
  • Lazy-import browser-only libraries so they stay out of the server bundle.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →