All posts
javascriptmodules

Fixing "Cannot use import statement outside a module"

Why this SyntaxError happens with ES module syntax, common causes across Node.js, browsers, and Jest, and how to fix each.

SR

Suhail Roushan

August 6, 2026

·
5 min read
·
0 views

SyntaxError: Cannot use import statement outside a module is the mirror image of the "exports is not defined" error — here, ES module import/export syntax is being parsed in a context expecting CommonJS or plain script syntax, which doesn't recognize import as valid syntax at all, producing a parse-time error before your code even runs.

This error means the JavaScript parser executing your file encountered import/export syntax without being told to treat the file as an ES module — depending on environment, this could be a missing "type": "module" in package.json, a missing type="module" on a script tag, or a test runner/tool not configured to handle ESM syntax.

Why This Error Happens

Unlike CommonJS's require(), which is just a regular function call valid in any JavaScript context, import/export are special syntax that requires the parser to know upfront it's parsing an ES module — this is a fundamental language design difference, not a limitation of any particular tool. Every environment executing your code needs an explicit signal that ESM syntax should be expected, and this error means that signal is missing somewhere in your specific execution path.

Reproducing the Error

Running an ESM-syntax file directly with plain Node.js without the module signal:

// script.js, package.json has no "type" field (defaults to commonjs)
import { formatDate } from "./utils.js";
console.log(formatDate(new Date()));
node script.js
# SyntaxError: Cannot use import statement outside a module

Jest running ESM-syntax source code without ESM configuration:

// A common Jest-specific version — source files use import/export,
// but Jest's default transform doesn't know to treat them as ESM
import { formatDate } from "../utils";
test("formats date", () => {
  expect(formatDate(new Date())).toBeDefined();
});
// SyntaxError: Cannot use import statement outside a module

Core Concepts Behind This Error

Each JavaScript execution environment needs its own explicit ESM signal, and they're all configured differently — Node.js via package.json's "type": "module" or .mjs extension, browsers via <script type="module">, and test runners/bundlers via their own specific transform or module-handling configuration; fixing one doesn't automatically fix the others.

Jest specifically has historically required extra configuration for ESM support beyond what a bundler like Vite or webpack needs, because Jest's default transform pipeline (Babel-based) needs explicit configuration to parse and transform import/export syntax rather than assuming CommonJS — this is one of the most common real-world sources of this specific error.

Node.js's native ESM support and CommonJS's require() have different resolution and interop rules, meaning fixing this error sometimes surfaces secondary issues (like needing file extensions in relative imports under native ESM, which CommonJS doesn't require) once the module type signal itself is corrected.

A script tag missing type="module" in an HTML file is the browser-specific version of this exact error — the browser parses the script as a classic script by default, and ESM syntax in that context fails identically to the Node.js case, just triggered by a different missing configuration signal.

Fixing "Cannot Use Import Statement Outside a Module"

Fix 1: For Node.js, add "type": "module" to package.json, or rename the file to .mjs:

// package.json
{ "type": "module" }

Fix 2: For browsers, add type="module" to the script tag:

<script type="module" src="script.js"></script>

Fix 3: For Jest, configure it to properly transform ESM syntax, either via Babel's preset-env module transform or Jest's native ESM support (requiring a specific Node flag and configuration):

// babel.config.js
module.exports = {
  presets: [["@babel/preset-env", { targets: { node: "current" } }]],
};
// package.json — Jest config for native ESM (alternative to Babel transform)
{ "scripts": { "test": "node --experimental-vm-modules node_modules/.bin/jest" } }

Fix 4: For a bundler (Vite, webpack) reporting this error unexpectedly, verify the file is actually being processed by the bundler's transform pipeline rather than served/executed directly outside of it, which sometimes happens with misconfigured build outputs or improperly excluded files.

Why Does This Error Sometimes Only Appear in Tests, Not the App Itself?

Because your application's actual runtime (a bundler-processed browser build, or a Node.js process with "type": "module" set) already has the ESM signal correctly configured, while your test runner is frequently a separate tool with its own independent configuration — Jest in particular runs source files through its own transform pipeline distinct from your app's build tooling, so it needs matching ESM configuration explicitly, which is easy to overlook since the app itself works fine.

Preventing This Error in Production

Keep module type configuration explicit and consistent across every tool that executes your code — application runtime, test runner, and any standalone scripts — rather than assuming one tool's correct configuration implies another's. When adopting ESM syntax in a project, verify test runner and build tool configuration as a deliberate step, since this is one of the most common places the module type signal is inconsistently applied.

If you hit this error, identify exactly which tool is throwing it (Node directly, a bundler, a test runner) first — the fix location and mechanism differ meaningfully between them, even though the underlying cause (missing ESM signal) is the same.

Related posts

Written by Suhail Roushan — Full-stack developer. More posts on AI, Next.js, and building products at suhailroushan.com/blog.

Get in touch