javascriptseverity: critical
ReferenceError: X is not defined

JavaScript ReferenceError: X is not defined — Variable or function not in scope

ReferenceError: variable is not defined

97% fixable~8 mindifficulty: beginner

Verified against MDN Web Docs — ReferenceError, ECMAScript 2022 spec §9.1.1.1, Node.js documentation · Updated June 2026

> quick_fix

Declare the variable with `let`, `const`, or `var` before using it, or add the correct `import` statement for the module that contains the function/class you are trying to use.

// BROKEN: using undeclared variable
console.log(userName); // ReferenceError if userName was never declared

// FIXED: declare before use
const userName = 'Alice';
console.log(userName);

// BROKEN: using a module export without importing
const result = parseDate('2026-01-01'); // ReferenceError if parseDate not imported

// FIXED: import the function
import { parseDate } from './utils/date.js';
const result = parseDate('2026-01-01');

// BROKEN: accessing browser global in Node.js
const w = window.innerWidth; // ReferenceError in Node.js

// FIXED: environment check
const w = typeof window !== 'undefined' ? window.innerWidth : 0;

What causes this error

ReferenceError is thrown when the JavaScript engine encounters an identifier (variable name, function name) that does not exist in any accessible scope. This happens when: a variable is used before it is declared (with `let`/`const` — the temporal dead zone), a variable from another module is used without importing it, a function was deleted or renamed, or a browser global (window, document) is accessed in a Node.js environment.

> advertisementAdSense placeholder

How to fix it

  1. 01

    step 1

    Check the exact name in the error message

    The error says 'ReferenceError: userName is not defined'. Check for typos: `userName` vs `username` vs `user_name`. JavaScript is case-sensitive — `UserName` and `userName` are different variables.

  2. 02

    step 2

    Declare the variable before use

    If the variable is supposed to exist, declare it: `const myVar = ...;` or `let myVar;`. With `let` and `const`, accessing the variable before its declaration line (even in the same block) throws a ReferenceError due to the temporal dead zone (TDZ).

  3. 03

    step 3

    Add the missing import statement

    In ES modules or bundled apps (Webpack, Vite), every cross-file dependency must be explicitly imported. If you use `debounce(fn, 200)` without importing it from lodash or a local utils file, you get a ReferenceError. Add: `import { debounce } from 'lodash';`

  4. 04

    step 4

    Check the execution environment

    Browser APIs (window, document, localStorage) cause ReferenceError in Node.js. Node.js globals (process, __dirname, Buffer) cause ReferenceError in browsers. For isomorphic/SSR code, guard: `if (typeof window !== 'undefined') { ... }`.

  5. 05

    step 5

    Check for temporal dead zone (TDZ) with let/const

    Unlike `var`, `let` and `const` are not hoisted to the top of their block. Accessing them before the declaration line throws ReferenceError: 'Cannot access X before initialization'. Move the declaration before any use, or restructure the code flow.

How to verify the fix

  • The console should show no ReferenceError after the fix
  • Search the file for the variable name — confirm exactly one declaration and all uses are after it
  • Run the code in both browser and Node.js if it needs to work in both environments

Why ReferenceError: X is not defined happens at the runtime level

JavaScript resolves identifiers through a scope chain. When the engine evaluates an identifier, it walks up the scope chain from the current lexical environment to the global environment. If the identifier is not found in any scope in the chain, the engine throws ReferenceError. For `let` and `const`, the variables are in the scope but in an 'uninitialized' state until the declaration is reached — this state transition from 'uninitialized' to 'initialized' is what creates the temporal dead zone.

Common debug mistakes for ReferenceError: X is not defined

  • Accessing `let` or `const` variables above their declaration line in the same function
  • Using a function or class from another file without adding the import statement
  • Case mismatches: `username` vs `userName` in a case-sensitive language
  • Assuming browser globals (window, fetch) work in Node.js scripts or vice versa

When ReferenceError: X is not defined signals a deeper problem

ReferenceError in a modern ES module codebase almost always means a missing import statement — a problem TypeScript catches at compile time. The recurring pattern is that developers rely on globally-available variables (jQuery's $, Lodash's _, browser globals) that were available in older module-less JavaScript but are no longer available in module-scoped files. The migration to ES modules is the right move, but it requires making all dependencies explicit, which is exactly what TypeScript's import checking enforces.

Editor's take

ReferenceError: X is not defined means JavaScript tried to read a variable that doesn't exist in the current scope chain. Unlike TypeError (which means the variable exists but you're using it wrong), ReferenceError means the name was never declared with `var`, `let`, `const`, or as a function/class declaration in any accessible scope. The most common production cause is a missing import statement — you're using a function from a library but forgot to import it, and the bundler didn't catch it because the reference is inside a conditional branch that wasn't exercised during build. In browser environments, this frequently hits when a script tag loads out of order or a CDN resource fails to load, leaving the global variable undefined. The temporal dead zone (TDZ) is another common trigger: accessing a `let` or `const` variable before its declaration line throws ReferenceError, even though the variable technically exists in the scope. This is different from `var`, which hoists the declaration (but not the assignment) and gives you `undefined` instead of an error. In server-side rendering, ReferenceError for `window`, `document`, or `localStorage` means you're running browser-specific code in a Node.js context. The fix is guarding with `typeof window !== 'undefined'` or moving the code to a `useEffect`. Understanding the difference between ReferenceError and 'undefined' is fundamental to debugging JavaScript scope issues.

By Bikram Nath · Curator · Updated June 2026

Frequently asked questions

What is the temporal dead zone (TDZ)?

The temporal dead zone is the period between entering a block and the execution reaching the `let` or `const` declaration. Within the TDZ, accessing the variable throws ReferenceError even though the variable name exists in scope (due to hoisting). This is intentional — it prevents a class of bugs caused by using `var`'s behaviour of returning undefined before declaration.

Why doesn't `var` throw ReferenceError but `let` and `const` do when accessed before declaration?

`var` declarations are hoisted to the top of their function scope and initialized to `undefined`. So accessing a `var` before its declaration returns `undefined` (a bug, but not a crash). `let` and `const` are hoisted to the top of their block scope but NOT initialized — accessing them before initialization throws ReferenceError (a crash that surfaces the bug immediately).

Can I use typeof to check if a variable exists without getting a ReferenceError?

Yes. `typeof undeclaredVar === 'undefined'` does NOT throw ReferenceError — it is the one operator that handles undeclared variables safely. This is the correct way to check for optional globals: `if (typeof gtag !== 'undefined') { gtag('event', ...) }`.

disclosure:Errordex runs AdSense, has zero third-party affiliate or sponsored links, and occasionally links to the editor’s own paid digital products (clearly labelled). Every fix is cross-referenced against the official sources listed in the “sources” sidebar before it ships. If a fix here didn’t work for you, please email so we can update the page.