Summary
A developer encounters Error [ERR_REQUIRE_ESM] when attempting to import the google-spreadsheet package using require() in a Node.js environment. This error occurs because the google-spreadsheet library is published as an ES Module (ESM) (using import syntax), while the project is running in CommonJS mode (using require syntax). Node.js does not allow mixing these two module systems directly via standard require() calls.
Root Cause
The specific technical mechanism causing this failure is the change in package.json configuration of the google-spreadsheet library.
- Package Definition: The library defines
"type": "module"in itspackage.jsonor exports itself strictly as an ES Module. - Runtime Restriction: Node.js throws
ERR_REQUIRE_ESMwhen code running in a CommonJS context (a file without.mjsextension or without"type": "module"in the project’spackage.json) attempts torequire()a dependency that is flagged as an ES Module. - Legacy vs. Modern:
require()is the legacy CommonJS system, whileimportis the modern ECMAScript standard. The error explicitly states that the legacy system cannot load the modern module.
Why This Happens in Real Systems
This error represents a growing industry-wide transition from CommonJS to ES Modules.
- Dependency Updates: Library maintainers are migrating to ES Modules to align with the JavaScript standard and improve tree-shaking. When a major dependency updates, it breaks the build for consumers stuck on the older CommonJS syntax.
- Cyclic Dependencies: ES Modules handle cyclic dependencies differently than CommonJS, which is often a reason libraries switch (static analysis allows better resolution).
- Environment Mismatch: Many older Node.js projects or scripts remain in CommonJS mode (
module.exports), while the ecosystem pushes toward ESM (export default).
Real-World Impact
- Build Failures: CI/CD pipelines will fail immediately if the lockfile updates or a fresh install pulls a version of the library that is strictly ESM.
- Refactoring Required: Teams cannot simply patch the import line; they often must convert large swaths of their codebase from
requiretoimport. - Tooling Compatibility: Older testing frameworks or bundlers that rely solely on CommonJS may cease to function or require complex configuration overrides to handle ESM.
Example or Code
To fix this, you must align your syntax with the package requirements. You cannot use require for this package anymore.
The Failing Code (CommonJS):
// This fails in a standard Node.js environment for ESM packages
const { GoogleSpreadsheet } = require('google-spreadsheet');
The Fix (Option A – Changing to Import Syntax):
You must change your file extension to .mjs or set "type": "module" in your package.json to use this syntax:
import { GoogleSpreadsheet } from 'google-spreadsheet';
async function main() {
const doc = new GoogleSpreadsheet('');
// ... your logic
}
main().catch(console.error);
The Fix (Option B – Dynamic Import in CommonJS):
If you must keep your file as CommonJS (.js without "type": "module"), use dynamic import(), which returns a Promise:
async function loadSheet() {
const { GoogleSpreadsheet } = await import('google-spreadsheet');
const doc = new GoogleSpreadsheet('');
// ... your logic
}
loadSheet();
How Senior Engineers Fix It
Senior engineers address this by choosing the path of long-term stability over short-term hacks.
- Project Migration: They usually migrate the entire project to ES Modules (renaming files to
.mjsor adding"type": "module"topackage.json). This is the “forward-looking” solution that aligns with the future of JavaScript. - Dynamic Imports for CJS Interop: If a full migration is impossible due to legacy code constraints, they utilize dynamic imports (
await import(...)) to bridge the gap between the CommonJS host and the ESM dependency. - Version Pinning (Temporary): As a stopgap, they might check the library changelog to find the last CommonJS-compatible version and pin to that in
package.json(e.g.,"google-spreadsheet": "4.1.1"), buying time for a proper refactor.
Why Juniors Miss It
Junior developers often struggle to debug this because they view require and import as interchangeable syntax variations rather than distinct module systems.
- Search Engine Confusion: “How to fix require import error” often leads to answers about circular dependencies or missing files, not module system mismatches.
- Black Box Mentality: They often assume the problem lies in the installation or the Node version (updating Node doesn’t fix the syntax mismatch), overlooking the need to change how they write the import statement itself.
- Copy-Pasting: They copy code snippets from tutorials written in CommonJS into a project that has evolved to require ESM, leading to immediate friction.