[Bug] Frontend SSR fails with `ReferenceError: document is not defined`
Summary
The production frontend intermittently fails during server-side rendering because browser-only code accesses document while the application is being evaluated on the server.
This results in an unhandled server-side rejection and can prevent the page or chat response from rendering correctly.
Environment
- Project: SurfSense
- Deployment platform: Railway
- Environment: Production
- Frontend framework: Next.js
- Next.js version shown in logs:
16.2.12 - Frontend deployment:
81a32cb9-4493-4c76-9b4d-d1737d50dbbc - Approximate occurrence:
2026-08-25 00:29 UTC
Production logs
ReferenceError: document is not defined
at <unknown> (.next/server/chunks/ssr/app_1lmx4fc._.js:1:79752)
at <unknown> (.next/server/chunks/ssr/app_1lmx4fc._.js:1:118732)
at module evaluation (.next/server/chunks/ssr/app_1lmx4fc._.js:1:118738)
...
⨯ unhandledRejection: ReferenceError: document is not definedActual behavior
- The Next.js server evaluates a module that references
document. - The server throws
ReferenceError: document is not defined. - The error is reported as an
unhandledRejection. - The page may fail to render, hydrate incorrectly, or show a chat interface that appears to stop responding.
- The production stack trace only points to the minified SSR chunk, so the exact source module has not yet been identified.
Expected behavior
- Server-side rendering should complete without accessing browser-only globals.
- The initial page should load and hydrate successfully.
- Chat messages and streamed model responses should render normally.
- Browser-only APIs such as
document,window, andnavigatorshould only be accessed on the client.
Additional evidence
The backend was still successfully processing chat requests while the frontend error occurred.
Backend logs showed successful chat streams, successful finalization, and completed tool calls during the same period. This indicates that at least some user reports of the model “stopping” may actually be caused by the frontend failing to render or hydrate the response, rather than by the model/provider failing.
Steps to reproduce
- Deploy the frontend to Railway production.
- Open the SurfSense application.
- Load a dashboard or chat page that uses SSR.
- Ask a question that produces a streamed response.
- Inspect the frontend deployment logs.
- Observe
ReferenceError: document is not defined.
The issue appeared in production after deployment. A subsequent update/redeploy made the problem stop reproducing, but the underlying regression should still be tracked.
Suspected cause
A client-only module or code path is being evaluated during SSR/module initialization and accesses document before the browser exists.
The production stack is minified and does not expose the original source file. Source maps or a local reproduction with the same build should be used to identify the exact module.
Suggested investigation
- Reproduce using the same production build with server source maps enabled.
- Search for browser-global access occurring:
- at module scope;
- during render;
- inside shared utilities imported by server components;
- inside code that is not explicitly client-only.
- Verify all usages of:
document;window;navigator;localStorage;sessionStorage.
- Check whether the affected module should:
- be moved into
useEffect; - be guarded with a browser check;
- be marked as a client component;
- be dynamically imported with SSR disabled.
- be moved into
Acceptance criteria
- No
ReferenceError: document is not definedappears in production logs. - No
unhandledRejectionis generated by frontend SSR. - Initial page rendering succeeds after a cold start.
- Client hydration succeeds without console errors.
- A streamed chat response is displayed correctly.
- A regression test or SSR smoke test covers the affected code path.
Source: MODSetter/SurfSense