Back

How to Fix 'Cannot use import statement outside a module'

How to Fix 'Cannot use import statement outside a module'

You write a clean import statement, run your code, and immediately hit this:

SyntaxError: Cannot use import statement outside a module

This JavaScript ES modules error is one of the most common sources of confusion for developers working across Node.js, browsers, and testing environments. The fix isn’t always the same — and applying the wrong one makes things worse. Here’s how to diagnose your situation and resolve it correctly.

Key Takeaways

  • This error is a module system mismatch, not a syntax mistake — your runtime expected CommonJS but encountered ES module import syntax.
  • In Node.js, set "type": "module" in package.json or use the .mjs file extension to opt into ESM.
  • In browsers, add type="module" to your <script> tag so the engine treats the file as an ES module.
  • In Jest, configure Babel to transform ESM to CommonJS, and adjust transformIgnorePatterns for ESM-only third-party packages.
  • Always diagnose your environment first — Node.js, browser, or test runner — before applying a fix.

Why This Error Happens

The error means your runtime encountered ES module syntax (import) but expected something else — usually CommonJS (require). It’s a module system mismatch, not a syntax mistake in your code.

JavaScript has two module systems:

SystemSyntaxDefault in
CommonJS (CJS)require()Node.js (legacy)
ES Modules (ESM)importBrowsers, modern Node.js

The runtime decides which system to use based on configuration — not the code itself. That’s why the same import statement works in one project and fails in another.

How to Fix the Import Statement Outside Module Error in Node.js

Node.js treats .js files as CommonJS unless "type": "module" is set in package.json. To use import, you need to explicitly opt into ESM.

Option 1: Set "type": "module" in package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module"
}

This tells Node.js to treat all .js files in the project as ES modules. See the official Node.js ES modules documentation for details on how Node determines module type.

Option 2: Use the .mjs file extension

Rename your file from app.js to app.mjs. Node.js always treats .mjs files as ESM, regardless of package.json.

Option 3: Use .cjs for CommonJS files

If your project uses "type": "module" but one file needs require(), give it a .cjs extension.

Important: Don’t just add "type": "module" without checking your other files. Any file using require(), module.exports, or __dirname will break under ESM.

Fixing the Error in Browser JavaScript

In browsers, static import only works inside a module script. If your <script> tag doesn’t declare type="module", the browser treats it as a classic script and rejects the import syntax.

<!-- This will throw the error -->
<script src="app.js"></script>

<!-- This works -->
<script type="module" src="app.js"></script>

This behavior is part of the standard JavaScript modules specification implemented by modern browsers.

Note that module scripts are scoped — variables declared inside one aren’t available globally. This is why you might add type="module" and then see a ReferenceError for a variable you expected to be global. The solution is to export and import values explicitly rather than relying on global scope.

Fixing the Error in Jest and Other Test Environments

Jest runs in Node.js and traditionally uses CommonJS by default, even if your source code uses ESM. This is a common source of the “cannot use import statement outside a module” error in test suites.

One approach is to configure Babel to transform ESM to CommonJS during testing:

// babel.config.js
module.exports = {
  presets: ['@babel/preset-env'],
}

Alternatively, Jest can be configured to run tests in native ESM mode if your project already uses ES modules. See the Jest ECMAScript Modules documentation for details.

If a third-party package (like swiper, lodash-es, or similar ESM-only libraries) is causing the error, you need to tell Jest to transform it instead of ignoring it:

// jest.config.js
module.exports = {
  transformIgnorePatterns: [
    '/node_modules/(?!(swiper|ssr-window|dom7)/)',
  ],
}

The key insight: transformIgnorePatterns uses a negative lookahead. You’re saying “ignore everything in node_modules except these packages.” Listing them in separate array entries won’t work — they must be combined in a single regex pattern with |.

TypeScript Configuration

If you’re using TypeScript, check your tsconfig.json. The module field controls what module syntax TypeScript emits in its compiled output:

{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ESNext"
  }
}

Setting module to CommonJS while writing import statements is valid TypeScript — the compiler will transform import into require() in the output. However, setting module to ESNext while running the output in a CommonJS Node.js environment (without "type": "module" in package.json) will trigger the error at runtime. Make sure your tsconfig.json module setting matches what your runtime actually expects.

Diagnose Before You Fix

The same error appears in different environments for different reasons. Before applying any fix, ask:

  • Where is the error occurring — Node.js, browser, or test runner?
  • What does your package.json "type" field say?
  • Are you using a bundler, or running files directly?

Answering those three questions points you to the right solution every time.

FAQs

Yes, but you need to use file extensions to distinguish them. Files with a .mjs extension are always treated as ES modules, and files with a .cjs extension are always treated as CommonJS, regardless of the type field in package.json. This lets you use both systems side by side in a single project.

No. Each package in node_modules has its own package.json, so your type field only applies to your project files. Dependencies define their own module system independently. The error usually comes from your own files or from importing an ESM-only dependency in a CommonJS context without proper transformation.

Bundlers like Webpack and Vite process import statements during the build step and produce a single output file. They resolve module syntax before the runtime ever sees it. When you run files directly in Node.js or a browser without a bundler, the runtime itself must understand the module format, which is where mismatches cause this error.

These CommonJS globals are not available in ES modules. Instead, you can reconstruct them using import.meta.url. For example, use new URL(import.meta.url).pathname to get the file path, or combine it with the path module and fileURLToPath from the url module to replicate __dirname behavior.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay