How to Fix the “SyntaxError: Cannot Use Import Statement Outside a Module” in Node.js

Have you ever started your Node.js app, only to see an error like SyntaxError: Cannot use import statement outside a module your heart sinks. You thought you were doing everything rightusing import, clean code, modular design. But instead you’re stuck. Don’t worry it’s not a mystical bug, and yes, you can fix it (and understand why it happened).

What on Behind the Scenes

Node.js supports two (or more) module systems, and your file is being treated as not a module that allows import statements. Specifically:

  • The import/export syntax comes from ES Modules (ESM).
  • The older Node.js default (and still common) system is CommonJS, using require() and module.exports.
    When you mix these systems without telling Node what you’re doing, you get this error.
  • The key thing: Node needs to know your files are ESM (or you’re using a compatible syntax) before you can use import. If it doesn’t, Node says “hey, you’re not in a module context so I won’t let you use import”.

Fix it in a Node.js Project

Here I walk you through a typical Node.js project, how to decide what module system you want, and how to implement it.

Decide your module system

When you start your project (or inherit one), you should ask:

  • Is the project using mostly require() and module.exports today? If yes → CommonJS might be simpler.
  • Do you want to use import/export syntax across your codebase? If yes → go with ES Modules (ESM).
    Sticking to one system reduces confusion. Mixing require() and import in the same file usually invites trouble. (Some posts mention this but don’t emphasise decision-making.)

If you choose CommonJS (stay with require)

If you’re staying with CommonJS:

  • Use require() and module.exports.
  • Make sure not to write import/export in your files (or if you do, you’ll have to use a transpiler).
  • Ensure your package.json does not specify "type": "module" (or explicitly uses "type": "commonjs" in Node versions that support it).
  • File extensions: .js is fine by default.
    If you see the “Cannot use import statement outside a module” error, likely you attempted import in a file Node treats as CommonJS. Fix it by converting to require() or by migrating to ESM.

If you choose ES Modules (use import/export)

If you want to use import and export, here’s how to set up your Node.js project:

  1. In your package.json (root of project) add:
{
  "type": "module",
  ...
}
  1. This tells Node: treat .js files as ESM by default.
  2. If you want to use .js files as CommonJS in a mixed setup, you can add "type": "module" and use .cjs extension for CommonJS files, or leave .js as CommonJS and use .mjs for ESM. Many posts mention this but don’t show examples. For instance:
    • utils.mjs → ESM
    • legacy.cjs → CommonJS
  3. Rename files if needed: use .mjs extension for modules if you don’t want to change package.json or if you have older setup.
  4. Ensure Node version supports ESM (prefer Node 14+; ESM got more stable in Node 16+).
  5. Use import { something } from './module.js'; (note the ./module.js includes extension unless using package resolution).
  6. No mixing of require() and import in the same file unless you handle dynamic imports or carefully manage interoperability.
  7. If using older modules (CommonJS only) inside ESM files, you can use dynamic import:
const mod = await import('./commonjs-module.cjs');
  1. or use the createRequire helper:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const oldMod = require('./oldFile.js');

Debugging the “Cannot use import statement outside a module” Error

When you still hit the error despite your setup, try these checks:

  • Open a terminal and run node -v. Make sure you’re on a supported version.
  • In your package.json, check the "type" field: if it’s missing or set to "commonjs", Node treats files as CommonJS by default. If you wrote import, that’s a mismatch.
  • Check file extension. If you’re using .js, Node might treat it as CommonJS unless "type":"module" is set.
  • In your code file, check for ambiguity: Are you using import but also require()? Are you mixing syntaxes?
  • Look at the error trace: it usually points exactly to the import line and says “outside a module”, telling you Node considered that file not to be an ES module.
  • If using a test framework (e.g., Jest), check its configuration: it may default to CommonJS and will choke on import unless configured.
  • If using a bundler or transpiler, check that the build step preserves module syntax or transforms correctly (some bundlers by default transpile modules to CommonJS, which may confuse Node).

Migrating a small Node.js project to ESM

Let’s say you have a small project with files: index.js, utils.js. You want to use import syntax going forward. Steps:

In package.json, add "type": "module".

Update utils.js:

// utils.js
export function greet(name) {
  return `Hello, ${name}!`;
}

Update index.js:

import { greet } from './utils.js';
console.log(greet('World'));

Edge Cases and Bonus Tips

  • Using .mjs vs .js: You can skip "type": "module" by naming ESM files .mjs. That ensures Node treats them as modules. Some blog posts mention this, but don’t show when that’s useful (e.g., mixed codebase or incremental migration).
  • Mixed modules in same app: If you have a legacy codebase with many require() uses, you might choose to keep CommonJS for now and gradually migrate to ESM. You can rename new modules to .mjs, or keep .js with "type": "module" and convert legacy files to .cjs. Having both systems is possible but adds complexity.
  • Transpilers and bundlers: If you use a tool like Babel or Webpack, they might transform import to require or vice versa. That means you could write ESM syntax but end up with CommonJS code at runtime. If Node then tries to interpret the file as ESM (because of "type": "module"), you might still hit issues. So, check your build step and output file type.
  • Testing frameworks: As mentioned earlier, Jest for example may default to CommonJS. You’ll need to configure it to handle ESM (for example via babel-jest or by setting "type": "module" and using .mjs files) else you’ll get the same error during tests.
  • Imports from node_modules: Some modules in node_modules are published as ESM (import/export) and others as CommonJS (require/exports). If you import an ESM module from a CommonJS file, Node might complain. One solution: switch your file to ESM or use dynamic import as described. A Reddit user described this: “It looks like the library you’re trying to use is using ES6 modules… You could hook up Babel … but probably easier would be to simply write your code using ES6 and then tell Node to run it as ES6 by adding type: "module".”
  • Version compatibility: Older Node.js versions (before ~12.x) had experimental support for ESM and required flags like --experimental-modules. Modern Node (14+, 16+) has stable ESM support. If you’re on an older version you might need that flag.
  • File path & extension quirks: When using ESM you often need to include file extensions in imports (e.g., import { x } from './file.js';). Omitting .js can cause mysterious errors. This is a nuance many posts gloss over.
  • Dynamic import(): In mixed environments you can use await import() (in async context) to load modules dynamically. This works in ESM contexts and can help when you need to load a module at runtime that doesn’t map cleanly into either system.

Fix Decision Matrix

Your situationWhat to do
New project, you want import/export syntaxUse ESM: set "type": "module" in package.json, use .js or .mjs, no mixing
Legacy project with many require(), don’t want big changes nowStay CommonJS: use require(), ensure "type" is not set to "module", convert gradually
Mixed modules (some old, some new)Use .cjs for old CommonJS, .mjs for new ESM; or set "type": "module" and convert old files carefully; use dynamic import for tricky cases
Unexpected “Cannot use import statement outside a module” errorDebug: check Node version, check "type" in package.json, check file extension, ensure correct syntax and file path, check test/bundler config

Final Thoughts

The error SyntaxError: Cannot use import statement outside a module may look scary, but it’s really a signal telling you: “Node is treating this file as non-module (CommonJS) but you used ES module syntax (import)”. Once you understand the distinction between CommonJS and ES Modules, and how Node decides which one you’re using (via package.json "type" or file extensions like .mjs/.cjs), it becomes straightforward.

Related blog posts