Circular require() dependency detected in CJS/ESM interop
Production Risk
Circular ESM/CJS interop can produce undefined exports, causing silent failures in production.
Thrown when Node.js detects a circular dependency while using require() to load an ES module that itself (directly or indirectly) requires the original module back. Because ESM is evaluated synchronously in the require() interop path introduced in Node.js 22, a cycle can produce an incomplete module binding.
- 1Module A requires Module B which requires Module A before A has finished initialising
- 2Mixing CJS require() and ESM import in a circular graph
- 3Barrel/index files that re-export everything from sibling modules forming a cycle
Occurs during module loading when require() resolves an ESM file that re-requires the original caller.
// a.cjs
const b = require('./b.mjs');
module.exports = { a: 1 };
// b.mjs — creates the cycle
import { a } from './a.cjs';
export const b = a + 1;expected output
node:internal/modules/esm/translators:Error [ERR_REQUIRE_CYCLE_MODULE]: Require cycle detected
Fix 1
Extract shared code into a third module
WHEN When two modules depend on each other
// shared.mjs
export const sharedValue = 1;
// a.mjs
import { sharedValue } from './shared.mjs';
// b.mjs
import { sharedValue } from './shared.mjs';Why this works
Breaking the cycle by introducing a dependency-free shared module eliminates the circular reference.
Fix 2
Use lazy imports inside functions
WHEN When the circular value is only needed at call time, not at module load time
// b.mjs
export async function getB() {
const { a } = await import('./a.mjs');
return a + 1;
}Why this works
Dynamic import() is deferred until the function executes, by which point all modules are fully initialised.
// a.cjs
const b = require('./b.mjs');
module.exports = { a: 1 };
// b.mjs — creates the cycle
import { a } from './a.cjs'; // this triggers ERR_REQUIRE_CYCLE_MODULEtry {
// operation that may throw ERR_REQUIRE_CYCLE_MODULE
riskyOperation()
} catch (err) {
if (err.code === 'ERR_REQUIRE_CYCLE_MODULE') {
console.error('ERR_REQUIRE_CYCLE_MODULE:', err.message)
} else {
throw err
}
}// Validate inputs before calling the operation
function safe_err_require_cycle_module(...args) {
// validate args here
return performOperation(...args)
}✕ Ignore the warning and ship
Incomplete bindings cause subtle runtime bugs that are hard to trace.
Node.js Error Codes Documentation
Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev