← Debugging Guides

阅读中文版本

Node.js — Cannot use import statement outside a module

Fix "Cannot use import statement outside a module" by aligning the package type, file extension and tooling with ES modules.

beginnerdebuggingnodeesm

Symptoms

  • SyntaxError: Cannot use import statement outside a module
  • The file works under ts-node but fails under plain node
  • Adding "type": "module" breaks require calls elsewhere
  • A third-party package uses CommonJS while the project uses ESM

Possible causes

  • The project is CommonJS but the file uses ESM import syntax
  • The file extension is .js while it should be .mjs, or the package type is not module
  • A build step that transpiles was skipped
  • Mixing require and import in one file

Diagnosis steps

Check package type and extension

node -p "require('./package.json').type" ; ls package.json *.mjs *.cjs

Interpretation

type module makes .js files ESM. Without it, .js is CommonJS and import syntax is invalid.

Reproduce with an explicit extension

mv file.js file.mjs && node file.mjs

Interpretation

If renaming to .mjs fixes it, the runtime was treating the file as CommonJS.

Look for mixed module syntax

grep -n "require(\|import " file.js

Interpretation

Mixing require and import in an ESM file fails because require is not defined there.

Root cause

The runtime classified the file as CommonJS, so ESM import syntax was a syntax error. The module system is chosen by extension and package type, not by the syntax used inside the file.

Fix

Set "type": "module" for an ESM project, use .mjs for individual ESM files, or transpile the source as part of the build. Avoid mixing require and import in the same file.

Verify the fix

Run the file again and confirm it parses and executes, then run the whole test suite to confirm other modules still load.

Symptom walkthrough

Running a file that uses import syntax fails with SyntaxError: Cannot use import statement outside a module. The file may work under a transpiler or test runner that implicitly enables ESM, hiding the problem until it runs under plain node or another tool. The error is about how the runtime classified the file, not about the import line itself.

Fix in practice

Choose a module strategy and apply it consistently: set type module in package.json for an ESM project, rename individual files to .mjs, or keep CommonJS and use require. When interoperating, import a CommonJS package from ESM rather than mixing syntax in one file.

Verification

Run the file again and confirm it executes, then run the broader test suite and any CLI entry points to confirm nothing else assumed the old module type.

Diagnostic commands

Check the behavior with commands like these:

node -p "require('./package.json').type" ; ls package.json *.mjs *.cjs
mv file.js file.mjs && node file.mjs
grep -n "require(\|import " file.js