Skip to main content

How to Resolve the "ReferenceError: document is not defined" Error in JavaScript

The ReferenceError: document is not defined error occurs when your JavaScript code attempts to access the document object in an environment where it does not exist. The document object is a core part of the browser's Web APIs and is not available in server-side JavaScript environments like Node.js.

This guide will explain the fundamental reason this error happens and provide the correct solutions for handling it in different contexts, including vanilla Node.js, server-side rendering (SSR) frameworks like Next.js, and React.

The Core Problem: Browser vs. Server Environments

It's crucial to understand the two different environments where your JavaScript code can run:

  • The Browser (Client-Side): This is the user's web browser (Chrome, Firefox, etc.). It provides a specific set of global variables and APIs for interacting with a web page, such as window, document, location, and navigator. The document object represents the HTML page itself and is the entry point for all DOM manipulation.

  • The Server (e.g., Node.js): This is a JavaScript runtime that runs on a server. It has its own set of built-in APIs for server-side tasks, such as fs (file system), http (networking), and process. It has no concept of a web page, and therefore, the document object is not defined.

The error is a clear signal that you are trying to run browser-specific code in a server environment.

Solution for Node.js: Avoid Browser Globals

If you are writing a script that is only intended to run in Node.js, you cannot use browser-specific APIs.

Example of problem:

// Problem: This code will crash when run with `node my_script.js`
console.log(document.title);

Error Output:

ReferenceError: document is not defined

Solution: you must use Node.js-specific APIs or libraries to achieve your goal. For example, if you need to parse an HTML file in Node.js, you would use a library like JSDOM or Cheerio.

// Example of using JSDOM in Node.js
const { JSDOM } = require('jsdom');

const dom = new JSDOM(`<!DOCTYPE html><p>Hello world</p>`);
const document = dom.window.document; // This is a simulated `document` object

console.log(document.querySelector('p').textContent); // Output: 'Hello world'

Solution for SSR (Next.js, etc.): The useEffect Hook

In frameworks that use Server-Side Rendering (SSR) or Static Site Generation (SSG) like Next.js, your component code often runs twice: once on the server to generate the initial HTML, and a second time on the client (the browser) to make it interactive.

The document is not defined error happens when code that needs the document object tries to run during the server-side build.

Example of problem:

// Problem: This will crash during the server-side render
// because `document` doesn't exist on the server.
function MyComponent() {
const title = document.title; // This line causes the error

return <div>The title is {title}</div>;
}

The solution is to place any code that needs to access the document or window objects inside a useEffect hook with an empty dependency array ([]). The useEffect hook only runs on the client side, after the component has mounted in the browser.

import { useState, useEffect } from 'react';

function MyComponent() {
const [title, setTitle] = useState('');

// Correct: This code will only run in the browser.
useEffect(() => {
setTitle(document.title);
}, []); // The empty array ensures this runs only once on mount.

return <div>The title is {title}</div>;
}

A Universal Check: typeof window

If you have a piece of code that needs to run in a "universal" context (both server and client), you can check for the existence of the window object to determine the current environment.

Solution:

if (typeof window !== 'undefined') {
// This code will only run on the client (in the browser)
console.log('Running on the browser, document is available.');
console.log(document.title);
} else {
// This code will only run on the server
console.log('Running on the server, document is not available.');
}
note

This is a reliable way to guard your browser-specific code and prevent it from running on the server.

A Common Mistake: Misspelling document

A less common but simple cause of the error is a typo. The document global object is always all lowercase.

Example of problem:

// Problem: 'Document' is capitalized.
const myElement = Document.getElementById('my-id');

Error Output:

ReferenceError: Document is not defined

The solution is to ensure the variable is spelled correctly in all lowercase.

// Correct: 'document' is all lowercase.
const myElement = document.getElementById('my-id');

Conclusion

The ReferenceError: document is not defined error is a fundamental indicator of an environment mismatch.

To solve it:

  • If you are in a Node.js environment, you cannot use the document object. You must use Node-specific libraries like JSDOM if you need to work with a DOM.
  • If you are in a React/Next.js component, move any code that accesses document or window inside a useEffect hook.
  • For "universal" code, use the check if (typeof window !== 'undefined') to ensure your browser-specific code only runs on the client.
  • Finally, double-check that you haven't simply misspelled document (it must be lowercase).