Fix: SyntaxError: Cannot use import statement outside a module
The file uses ES module import syntax, but Node or the browser is loading it as a classic script or CommonJS. Tell the runtime the file is a module.
Not checked by a trusted editor yet Last edited Outdated?
You see this when a file contains import ... from ... but is executed as CommonJS (in Node) or as a classic script (in the browser):
import { readFile } from "node:fs/promises";
^^^^^^
SyntaxError: Cannot use import statement outside a module
Why it happens
JavaScript has two module systems. ES modules (ESM) use import/export and are the standard in browsers and modern Node. CommonJS (CJS) uses require()/module.exports and was Node’s original system. Node decides which one a file uses before running it:
.mjsfiles are always ESM;.cjsfiles are always CommonJS..jsfiles follow the"type"field in the nearestpackage.json:"module"means ESM,"commonjs"means CommonJS.- With no
"type"field, recent Node versions (22.7 and later) try to detect ESM syntax automatically; older versions treat the file as CommonJS and throw this error.
So the error usually means the file is a .cjs file, the package says "type": "commonjs", or you are on an older Node.
Fix in Node
Pick one of these, in order of preference:
- Add
"type": "module"to yourpackage.json. All.jsfiles in that package become ES modules. - Or rename just that file to
.mjs. - Or, if the project must stay CommonJS, use
require()in that file, or load an ES-only package with dynamicawait import("pkg")inside an async function.
{
"name": "my-app",
"type": "module"
}
Things that change after switching to ESM
require,module.exports,__dirnameand__filenamedo not exist. Useimport/export, andimport.meta.dirname/import.meta.filename(Node 20.11+).- Relative imports need the file extension:
import { x } from "./utils.js", not"./utils". - Importing JSON needs an import attribute:
import data from "./data.json" with { type: "json" }. - Importing a CommonJS package gives you its
module.exportsas the default export; named imports work only when Node can detect them statically. - Any remaining CommonJS files can be renamed to
.cjsso they keep working.
Going the other way, Node 20.19+ and 22.12+ can require() a synchronous ES module, which makes mixed projects much easier than they used to be.
Fix in the browser
A plain <script> tag loads a classic script. Mark it as a module:
<script type="module" src="/js/app.js"></script>
Module scripts are deferred automatically and run in strict mode, and they only load over HTTP(S). Opening the page from file:// usually fails because of CORS rules, so use a local dev server.
Fix in tools and test runners
- TypeScript: check
"module"intsconfig.json. For Node projects,"module": "nodenext"makes the compiled output follow yourpackage.jsontype. - ts-node: this error is a common symptom of ESM projects run with the CommonJS loader. Alternatives are
tsxor Node’s built-in type stripping. - Jest: it runs CommonJS by default and transforms your code; an ES-only dependency in
node_modulesis not transformed. AdjusttransformIgnorePatterns, enable Jest’s ESM support, or use a runner with native ESM such as Vitest ornode --test.
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0021 Read and write files in Node.js with fs/promises A complete Node script that walks a folder, reads text files, and writes a JSON report safely, showing the everyday fs/promises calls… Beginner · Step by step · Any system Script Node.js 15 Oct 2026
- 0022 Build a small Node.js CLI with util.parseArgs A complete, dependency-free command-line tool in Node: options and flags with parseArgs, input from files or a pipe, help text, and meaningful… Intermediate · Step by step · Any system Script Node.js 15 Oct 2026
- 0026 Fix: TypeError: Cannot read properties of undefined (reading ‘x’) You tried to read a property from a value that is undefined or null. Find which value is missing, then guard it… Beginner · Fixes an error · Any system Article Basics · Common errors 15 Oct 2026
- 0088 Fix: Access to fetch at ‘…’ from origin ‘…’ has been blocked by CORS policy The browser refused to give your script a cross-origin response because the server did not send the right Access-Control-* headers. Fix it… Intermediate · Fixes an error · Browser Article Common errors · Making requests 15 Oct 2026
- 0263 Build a notes REST API with plain Node.js: CRUD, validation, status codes and CORS Write a small JSON API for notes using only Node.js built-ins: create, read, update and delete, input validation, correct HTTP status codes,… Intermediate · Guided project · Any system Article Making requests · Node.js · Status codes 15 Oct 2026
- 0319 Fix: npm ERR! EACCES permission denied npm cannot write to a directory it needs: the global install location, its cache in ~/.npm, or a node_modules owned by root.… Beginner · Fixes an error · Linux, macOS Article Common errors · Node.js 15 Oct 2026
Repos in the wild
- Node.js nodejs/node The source of the Node.js runtime: a JavaScript engine (V8) plus APIs for files, networking, processes and more, used to run JavaScript outside the browser. GitHub
- Express (expressjs/express) expressjs/express A minimal and flexible web framework for Node.js, built around routes and middleware, and the foundation of countless APIs and other frameworks. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Commitpedia +3,110 chars