SyntaxError: Cannot use import statement outside a module

The file uses import, but whatever is running it thinks it is an old-style CommonJS script (or, in a browser, a classic script). Tell the runtime the file is an ES module, or stop mixing the two systems.

Two module systems

CommonJS (CJS)ES modules (ESM)
Syntaxconst x = require('x'), module.exportsimport x from 'x', export
Node picks it when.cjs, or .js with no "type" / "type": "commonjs".mjs, or .js with "type": "module"
BrowserNot supported natively<script type="module">

The error means an import line landed in code the runtime is treating as the left-hand column.

Fix in Node

// package.json (nearest one to the file)
{
  "type": "module"
}

Or rename just that file to file.mjs. After switching, the reverse problems appear: require is not defined in ES module scope (use import, or createRequire from node:module), __dirname is not defined (use import.meta.dirname on Node 20.11+, or path.dirname(fileURLToPath(import.meta.url))), and relative imports need the extension: import './util.js', not './util'. Recent Node versions (22.12+) can also require() many ES modules, which softens some of this.

Validate the edited package.json in the JSON formatter: a stray comma there produces a different, more confusing error.

Fix in the browser

<!-- wrong: classic script -->
<script src="/app.js"></script>
<!-- right -->
<script type="module" src="/app.js"></script>

Module scripts are deferred automatically, run in strict mode, and must be served over HTTP(S) with a JavaScript MIME type. Opening the page from file:// triggers a CORS error instead, so use a local dev server. Bare imports like import React from 'react' do not work in the browser without a bundler (Vite, esbuild) or an import map.

Fix in TypeScript and ts-node

Fix in Jest

Jest runs tests as CommonJS by default. Either let Babel or ts-jest transform import into require, or run Jest in native ESM mode (NODE_OPTIONS=--experimental-vm-modules npx jest). When the failing file is inside node_modules (an ESM-only package), add it to transformIgnorePatterns exceptions, or move to Vitest, which is ESM-first.

When it is inside a dependency

If the stack trace points into node_modules/some-package, that package became ESM-only in a major version. Options: import it from an ESM file, use dynamic await import('some-package') from CJS, or pin the last CommonJS major. Compare the two lockfiles in the text diff tool to see which version jumped.

Related

npm ERR! code ENOENT · ModuleNotFoundError (Python) · Node OpenSSL digital envelope error · Refused to execute inline script (CSP) · npm ERR! code ELIFECYCLE · Module not found: Can't resolve · Cannot find module (Node)

Questions

What causes 'Cannot use import statement outside a module'?

An import statement is in a file that Node, Jest or the browser is running as CommonJS or a classic script. Mark the file as an ES module or convert the import to require.

How do I fix it in Node.js?

Add "type": "module" to the nearest package.json, or rename the file to .mjs. Then use file extensions in relative imports and import.meta instead of __dirname.

How do I fix it in the browser?

Load the script with <script type="module" src="..."> and serve the page from a web server rather than file://.

Why does Jest show this error?

Jest uses CommonJS by default. Add a Babel or ts-jest transform, run Jest with --experimental-vm-modules, or switch to Vitest. ESM-only packages in node_modules also need a transformIgnorePatterns exception.

Can I mix require and import?

In an ES module, use createRequire to load CommonJS-only code. In CommonJS, use dynamic await import() for ESM-only packages. Newer Node versions can require() many ES modules directly.

Published .

Try it

Related guides

Newest guides