No circular dependencies
Why it matters
Circular dependencies cause modules to receive undefined at initialization time because JavaScript resolves the cycle by partially evaluating one module before the other is ready. This produces runtime bugs that are invisible to the type system and nearly impossible to reproduce reliably. CWE-1120 (Excessive Complexity) applies: circular graphs make the build tool's evaluation order non-deterministic and prevent tree-shaking, silently bloating your bundle. AI-generated codebases are especially prone to cycles because utility files get written to "reach back up" into components they originally served.
Severity rationale
Critical because circular imports can produce silent `undefined` values at runtime that bypass type checking and are extremely difficult to trace back to their root cause.
Remediation
Find all cycles first, then break them by moving shared logic to a file that neither participant imports. Run:
npx madge --circular src/
# or
npx dpdm --circular src/
To break a cycle: extract the shared code into a new neutral module, or use dependency injection. Prevent future cycles by adding eslint-plugin-import with the import/no-cycle rule — it fails the lint check the moment a cycle is introduced.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Code Maintainability Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- iso-25010:2011 · maintainability.modularity — Modularity
- iso-25010:2011 · maintainability.analysability — Analysability
- cwe · CWE-1120 — Excessive Code Complexity
Taxons
History
- 2026-04-18·v1.0.0·Initial import from code-maintainability·automated