JavaScript “is not defined”: Fix Scope, Imports & Load Order
ReferenceError: x is not defined means JavaScript could not resolve the identifier x in the active lexical/module/global environment. Start from the exact identifier and first application stack frame. Do not treat it as an undefined object property, package-install problem, or generic bundler failure until you prove who was supposed to define that name.
ReferenceError: ... is not defined.The name is a variable, function, imported symbol or library global.The error appears when code first tries to read that identifier.First-party reproduction run on Oct 29, 2026 in Node.js v24.22.1: reading an undeclared name produced “ReferenceError: formatValue is not defined”; declaring it before use printed 42. This confirms the basic missing-identifier case in Node.js only. Browser script order, module loading and bundler output need checks in their own runtime.
node -e 'console.log(formatValue)'
# ReferenceError: formatValue is not defined
node -e 'const formatValue = value => String(value); console.log(formatValue(42))'
# 42Verify: You can now name the expected owner: local/enclosing declaration, explicit module import, or intentional browser global. If the failing expression is property access on an already-resolved value, this is the wrong error class.
Why this happens
This error is about identifier resolution. The name may never have been declared, may be outside the current block/function/module scope, may be missing an import, or may be an expected browser global that was never created. This differs from obj.x where obj resolves but its value/property is wrong—that usually produces a TypeError or undefined value rather than saying identifier x is not defined.
Diagnose before changing more
JavaScript identifiers are case-sensitive, so
userData and userdata are different names.Values declared with
let or const inside a block are not visible outside that block.Confirm that the import exists or that the dependency script loads before code that uses its global.
Module code has its own scope and should use explicit imports/exports. Do not assume a top-level module binding is a property on
window.Read the actual execution semantics. Merely placing one script tag above another is not sufficient when
async allows independent execution timing.Inspect the emitted/imported symbol and failing bundle/chunk rather than creating a global workaround in source.
Fix #2 — declare or import the identifier in the correct scope
If the name belongs to your code, declare it before use or import/export it through the module boundary that needs it. Avoid creating accidental globals just to silence the error.
// module-a.js
export function formatValue(v) { return String(v); }
// module-b.js
import { formatValue } from './module-a.js';Verify: Reload or rerun the exact failing path. The original ReferenceError should disappear; if a different error appears, follow that new error instead of continuing to change scope.
Fix #3 — browser global: prove load success, export and execution order
If the identifier is intentionally provided by a classic browser library, verify three separate facts: the request succeeded, that build/version actually creates the expected global, and the provider executes before the consumer. For module-based libraries, use the documented import instead of assuming a global exists.
<script src="library.js"></script>\n<script src="app.js"></script>async scripts execute when available and can break an assumed provider→consumer order. defer and module scripts have different scheduling semantics. Check the actual tags before “fixing” order by moving lines around.Verify: Reload the page with DevTools Network open. The dependency request should succeed, and the first stack frame should no longer report the missing global.
What not to do
window.x just to make a module-scoped import/declaration visible globally.Do not assume moving an async script tag higher guarantees it executes first.Do not install/reinstall an npm package merely because its expected identifier is missing; first prove the import or global that should create the identifier.Still seeing the error?
If source code appears to contain the name but the runtime still reports it undefined, inspect the runtime context that produced the stack trace: exact module/file, emitted bundle, route and script execution order. For bundlers, confirm that the expected import survives into the failing output and that you are debugging the same build being served. Do not classify every chunk/dynamic-import failure as this ReferenceError; follow the first concrete runtime/network/module error when it differs.
References and related guides
Still stuck? Ask the community
Share your operating system, software version, exact error text, and which fix you already tried. Another reader may have seen the same setup.
Loading community discussion…
Comments could not load here. Open ErrorHarbor Discussions on GitHub →