agentsclimarketplace

Node cjs esm mismatch

Skill viditkbhatnagar/immunize/src/immunize/patterns/node-cjs-esm-mismatch

A curated pattern library that stops AI coding assistants from repeating common runtime errors. No API key. No LLM calls at runtime.

Install
npx -y skills add viditkbhatnagar/immunize --skill node-cjs-esm-mismatch

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when writing Node.js modules to keep CommonJS (require) and ES Module (import/export) syntax consistent within a single file and aligned with the package's module type.

SKILL.md

2.4 KB, as published. Nobody here has run it

node-cjs-esm-mismatch

Pick one module system per file and stick with it. Mixing require(...) and import in the same Node module crashes at load time:

ReferenceError: require is not defined in ES module scope
SyntaxError: Cannot use import statement outside a module

Node decides the module system per file by these rules, in order:

  1. File extension wins: .mjs is always ESM, .cjs is always CJS.
  2. Otherwise, the closest enclosing package.json decides via "type": "module" (ESM) or "type": "commonjs" (CJS, the default).

Once a file is loaded as ESM, require does not exist. Once a file is loaded as CJS, top-level import is a syntax error.

Example

Wrong — mixed syntax in a .mjs file:

// readers.mjs
const fs = require("fs");
import path from "path";

export function readFirstLine(filename) {
  return fs.readFileSync(filename, "utf8").split(path.sep)[0];
}

Right — consistent ESM:

// readers.mjs
import fs from "fs";
import path from "path";

export function readFirstLine(filename) {
  return fs.readFileSync(filename, "utf8").split(path.sep)[0];
}

Or consistent CJS:

// readers.cjs
const fs = require("fs");
const path = require("path");

function readFirstLine(filename) {
  return fs.readFileSync(filename, "utf8").split(path.sep)[0];
}
module.exports = { readFirstLine };

When you actually need both

Inside an ESM file, import("...") (the dynamic-import expression) is the only way to load a CJS module — never call require. Inside a CJS file, you cannot synchronously load ESM at all; either rewrite the caller as ESM or use top-level await with dynamic import() in a small ESM bridge file.

Don't reach for createRequire

createRequire(import.meta.url) papers over the bug instead of fixing it: it gives you a working require inside an ESM file, but downstream tooling (bundlers, type checkers, the Node loader hooks) treats the file inconsistently. Pick one module system and convert the rest of the file to match.

Immunity note

The verification scans the fixture for require(...) calls in an .mjs file. The repro mixes require with import and fails the assertion; the fix uses import consistently and passes.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.