Circular Dependency in Node.js
Currently I am working on some project in Node.js. Everything was going well. Suddenly, I started getting this frustrating error:
TypeError: generateTransactionRefNumber is not a functionAt first, I thought it was a typo or a wrong import. But after double-checking everything, the issue persisted.
What Was Happening?
I had a service-based architecture with two key files:
UtilityService.js– Handles common utility functions.TransactionService.js– Manages transaction-related logic.
Both services depended on each other.
UtilityServiceneeded a method from.TransactionServiceTransactionServiceneeded a method from.UtilityService
This created a circular dependency, meaning Node.js couldn’t fully load one module before the other.
How I Debugged It
- Used
madgeto Detect Circular Dependencies
npx madge --circular ./And got this output:
✖ Found 1 circular dependencies!
...
1) services/UtilityService.js > services/TransactionService.js2. Identified the issue,
UtilityServicewas importingTransactionServiceTransactionServicewas importingUtilityService
This meant that when Node.js tried to load them, one of them was partially loaded, leading to undefinederrors (yeah, it says undefined 😏).
The Solution: Extract Shared Logic
Instead of having the two services depend on each other, I
- Created a New Helper File (
TransactionHelper.js)
- Moved shared functions (like
generateTransactionRefNumber) into this file.
2. Updated Imports
- Both services now import
TransactionHelperinstead of each other
Before (Circular Dependency)
// UtilityService.js
const TransactionService = require("./TransactionService"); // Bad
// TransactionService.js
const UtilityService = require("./UtilityService"); // BadAfter
// UtilityService.js
const TransactionHelper = require("./TransactionHelper"); // good and right way
// TransactionService.js
const TransactionHelper = require("./TransactionHelper"); // good and right wayWhy This Works
- No More Circular Chain:
UtilityService→TransactionHelperTransactionService→TransactionHelper- No Partial Loading: All dependencies resolve correctly.
Recommendation
- Avoid Mutual Imports: Services shouldn’t depend on each other directly.
- Use Helper Files: Extract shared logic to break circular dependencies.
- Check with
madge: Detect circular dependencies early
Hope it will help you.
check out other articles
Get Ermiyas Damte’s stories in your inbox
Join Medium for free to get updates from this writer.






