Coding tips

ReferenceError: x is not defined in JavaScript: 10 Causes and Fixes, from Typos and TDZ to require, __dirname and window in Node (Tested Examples)

JavaScript throws ReferenceError: x is not defined when it cannot find a variable with that name in any scope. Here are 10 tested causes in Node.js 24 and Chrome, from typos, block scope and the temporal dead zone to require, __dirname and window in ES modules and Node.

By 9 min read 0 views
Cover image for ReferenceError: x is not defined in JavaScript: 10 Causes and Fixes, from Typos and TDZ to require, __dirname and window in Node (Tested Examples)

ReferenceError: x is not defined means JavaScript looked for a variable named x in every scope, from the current block up to the global scope, and found nothing. The usual causes are a typo, a variable declared inside a different block or function, a module you never imported (such as fs), browser globals like window in Node.js, and CommonJS names like require or __dirname inside an ES module. A related message, Cannot access 'x' before initialization, means the variable exists but you used it above its let or const line.

A ReferenceError is different from a TypeError. undefined is a value; "not defined" means there is no variable at all. If the variable exists but holds the wrong thing, you get errors like TypeError: x is not a function instead.

Every error below was produced with Node.js v24.22.1, and the main ones were checked again in headless Chrome 156. Stack trace lines starting with at are trimmed.

In this guide:

  • Cause 1: A typo in the variable name
  • Cause 2: Using let or const before its line (TDZ)
  • Cause 3: The variable lives in a different block
  • Cause 4: A Node.js module you never imported
  • Cause 5: require is not defined in ES module scope
  • Cause 6: __dirname and exports in ES modules
  • Cause 7: window or document in Node.js (and SSR)
  • Cause 8: Implicit globals in strict mode
  • Cause 9: Function expressions are not hoisted like declarations
  • Cause 10: $ or another library is not loaded
  • Same errors in the browser
  • The fixes in one file
  • Frequently asked questions

Cause 1: A typo in the variable name

const userName = "Ana";
console.log(username);
c01_typo.cjs:2
console.log(username);
            ^

ReferenceError: username is not defined

JavaScript names are case-sensitive, so userName and username are different variables. The caret points at the exact name. Search the file for the declaration and copy its spelling. Editors with TypeScript checking, even in plain .js files, underline this before you run the code. My free tools page has browser-based helpers for quick checks like this.

Cause 2: Using let or const before its line (TDZ)

console.log(total);
let total = 10;
c02_tdz.cjs:1
console.log(total);
            ^

ReferenceError: Cannot access 'total' before initialization

Variables declared with let, const and class exist from the start of their block, but you cannot touch them until the declaration line runs. That gap is the temporal dead zone. var would have printed undefined instead. The fix is to move the declaration above its first use. My post on var vs let vs const covers hoisting in more detail.

Cause 3: The variable lives in a different block

if (true) {
  const message = "inside";
}
console.log(message);
c03_block_scope.cjs:4
console.log(message);
            ^

ReferenceError: message is not defined

let and const are block-scoped, so message only exists inside the if braces. The same applies to variables declared inside a function, a loop, or a try block that you use in the catch. Declare the variable in the outer scope and assign it inside the block (see the fixes file at the end).

Cause 4: A Node.js module you never imported

const text = fs.readFileSync("notes.txt", "utf8");
c04_missing_require.cjs:1
const text = fs.readFileSync("notes.txt", "utf8");
             ^

ReferenceError: fs is not defined

Built-in modules such as fs, path and os are not globals. Import them first with const fs = require("node:fs") in CommonJS or import fs from "node:fs" in an ES module. Code copied from a tutorial often skips the import line at the top.

Cause 5: require is not defined in ES module scope

const path = require("node:path");
console.log(path.join("a", "b"));
esm/c05_require.js:1
const path = require("node:path");
             ^

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

Node.js treats a .js file as an ES module when the nearest package.json has "type": "module", or when the file ends in .mjs. ES modules have no require. Node prints a helpful hint after the error. You can switch to import, rename the file to .cjs, or create a require function (shown below). In the browser, Chrome prints just require is not defined, because browsers never had require.

The opposite mistake, an import in a CommonJS file, gives Cannot use import statement outside a module.

Cause 6: __dirname and exports in ES modules

console.log(__dirname);
esm/c06_dirname.js:1
console.log(__dirname);
            ^

ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
exports.sum = (a, b) => a + b;
esm/c11_exports.js:1
exports.sum = (a, b) => a + b;
^

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

__dirname, __filename, exports and module are injected into CommonJS files only. Here are the ES module replacements, all tested:

import path from "node:path";
import { fileURLToPath } from "node:url";
import { createRequire } from "node:module";

console.log(path.join("a", "b"));
console.log(import.meta.dirname === path.dirname(fileURLToPath(import.meta.url)));
const require = createRequire(import.meta.url);
console.log(typeof require("node:os").platform());
export const sum = (a, b) => a + b;
a/b
true
string

import.meta.dirname is available in current Node.js releases, and path.dirname(fileURLToPath(import.meta.url)) works on older ones. Both are described in the Node.js ES modules documentation.

Cause 7: window or document in Node.js (and SSR)

const width = window.innerWidth;
c07_window.cjs:1
const width = window.innerWidth;
              ^

ReferenceError: window is not defined

window, document and localStorage exist only in browsers. You see this in Node scripts, tests, and in server-side rendering in frameworks like Next.js, where component code runs on the server first. Guard it with typeof, which never throws for undeclared names:

console.log(typeof notDeclaredAnywhere);
console.log(typeof window === "undefined" ? "running in Node" : "running in a browser");
console.log("window" in globalThis, "process" in globalThis);
undefined
running in Node
false true

In React, move browser-only code into useEffect, which runs only in the browser. Use globalThis when you need the global object in any environment.

Cause 8: Implicit globals in strict mode

count = 1;
console.log("sloppy mode created a global:", globalThis.count);
sloppy mode created a global: 1
count = 1;
console.log(count);
esm/c08_implicit_global.js:1
count = 1;
      ^

ReferenceError: count is not defined

The same two lines behave differently. In a sloppy-mode CommonJS script, assigning to an undeclared name silently creates a global. ES modules and classes are always in strict mode, so the same assignment throws. That is why old code can break when you convert it to modules. Add let or const.

Cause 9: Function expressions are not hoisted like declarations

console.log(add(2, 3));
function add(a, b) { return a + b; }
console.log(multiply(2, 3));
const multiply = (a, b) => a * b;
5
c09_function_expr.cjs:3
console.log(multiply(2, 3));
            ^

ReferenceError: Cannot access 'multiply' before initialization

add is a function declaration, so it works above its line. multiply is an arrow function stored in a const, so it follows the TDZ rule from cause 2. Either define arrow functions before you call them, or use a function declaration.

Cause 10: $ or another library is not loaded

$(".button").hide();
c10_jquery.cjs:1
$(".button").hide();
^

ReferenceError: $ is not defined

$ is not defined, React is not defined or google is not defined mean the library's script has not run yet. Check that its <script> tag comes before yours, that the CDN URL loads (look at the Network tab), and that an ad blocker is not stopping it. With bundlers, import the library instead of relying on a global.

Same errors in the browser

Chrome 156.0.8078.47
username -> ReferenceError: username is not defined
(() => { console.log(t); let t = 1; })() -> ReferenceError: Cannot access 't' before initialization
require('fs') -> ReferenceError: require is not defined
$('.x') -> ReferenceError: $ is not defined

Chrome uses the same V8 engine as Node.js, so the messages match, except that the require message has no ES module hint. Firefox words some of them differently, but the MDN page for this error lists the causes for all browsers.

The fixes in one file

const fs = require("node:fs");
fs.writeFileSync("/tmp/notes.txt", "hello");
console.log(fs.readFileSync("/tmp/notes.txt", "utf8"));

let message;
if (true) {
  message = "inside";
}
console.log(message);

let total = 10;
console.log(total);
hello
inside
10
MessageUsual causeFix
x is not definedTypo, wrong scope, or never declaredFix the name or declare it in an outer scope
Cannot access 'x' before initializationlet/const/class used above its line (TDZ)Move the declaration up
fs is not definedNode module used without require/importconst fs = require("node:fs")
window / document is not definedBrowser code running in Node or during SSRCheck typeof window or run it in the browser
require is not defined in ES module scopeCommonJS code in an ES moduleimport or createRequire()
__dirname is not defined in ES module scopeCommonJS variable in an ES moduleimport.meta.dirname
exports is not defined in ES module scopemodule.exports style in an ES moduleexport
$ is not definedjQuery not loaded, or loaded after your scriptLoad the library first

Missing packages are a different problem: require("lodash") without installing it gives Error: Cannot find module, not a ReferenceError.

Frequently asked questions

What does ReferenceError: x is not defined mean?

JavaScript could not find any variable named x in the current scope or any outer scope. It was never declared, was misspelled, or was declared in a different block or file.

What is the difference between not defined and undefined?

undefined is a value a declared variable can hold. Not defined means no variable with that name exists, and reading it throws a ReferenceError.

What does Cannot access before initialization mean?

The variable is declared with let, const or class, but you used it above the declaration line, inside the temporal dead zone. Move the declaration up.

How do I fix require is not defined in ES module scope?

Use import instead, rename the file to .cjs, or create require with createRequire(import.meta.url) from node:module.

How do I get __dirname in an ES module?

Use import.meta.dirname in current Node.js, or path.dirname(fileURLToPath(import.meta.url)) on older versions.

How do I fix window is not defined in Next.js?

Code that touches window ran on the server. Move it into useEffect, or guard it with typeof window !== "undefined".

How can I check if a variable exists without an error?

Use typeof: typeof name === "undefined" does not throw even when name was never declared, except inside its own TDZ.

Last checked: 9 November 2026. Figures, settings and guidance can change, so confirm anything important with the sources linked above.

Share X LinkedIn WhatsApp Facebook
Was this helpful?

0%