From MODULE_NOT_FOUND to a Verified AI Token Balance: Debugging MyZubster
A small backend deployment issue turned into a useful debugging session.
While working on MyZubster, my Node.js/Express backend, the application initially failed to load because several route modules referenced by server.js did not exist at the expected paths.
The first error
The first failure was:
Error: Cannot find module './src/routes/geocodeRoutes'
The server contained:
const geocodeRoutes = require('./src/routes/geocodeRoutes');
app.use('/api/geocode', geocodeRoutes);
But the actual route file available in the project was:
src/routes/mapRoutes.js
The route itself was valid and exported an Express router:
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.json({ message: 'Map routes - placeholder' });
});
module.exports = router;
So the first fix was simply aligning the import with the actual file:
const geocodeRoutes = require('./src/routes/mapRoutes');
The next missing module
After fixing that, Node.js exposed another missing dependency:
Error: Cannot find module './src/routes/healthRoutes'
There was no healthRoutes.js in src/routes.
However, the project already had the health/status endpoints in:
src/api/routes.js
That file contained endpoints such as:
router.get('/health', (req, res) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
Instead of creating a duplicate route file, I reused the existing API router:
const healthRoutes = require('./src/api/routes');
and mounted it with:
app.use('/', healthRoutes);
This made the server load successfully:
SERVER LOAD OK
✅ Connected to MongoDB
Verifying the AI forwarding API
The next issue was that the AI balance endpoint initially returned:
{
"success": true,
"userId": "DanielIoni-creator",
"model": "deepseek-chat",
"totalRemaining": 0,
"contracts": []
}
That suggested the route was working, but the database query wasn't finding the expected contract.
The controller uses:
const contracts = await AIContract.find({
userId,
model,
status: 'active',
expiresAt: { $gte: new Date() }
});
The AIContract model stores:
userId: String
model: String
tokens: Number
consumedTokens: Number
status: String
expiresAt: Date
So the next step was to inspect the actual MongoDB data rather than changing the controller blindly.
Finding the real database configuration
The application was using:
mongoose.connect(
process.env.MONGO_URI || 'mongodb://localhost:27017/myzubster'
);
But .env contained:
MONGODB_URI=...
rather than MONGO_URI.
That explained why standalone diagnostic scripts using:
process.env.MONGO_URI
received:
undefined
The important lesson here was to distinguish between:
- the variable name used by the application;
- the variable name actually present in
.env; - and the environment inherited by PM2.
After aligning the environment configuration, the database could be queried correctly.
The contract was there
The MongoDB inspection showed exactly one AI contract:
userId: DanielIoni-creator
model: deepseek-chat
tokens: 1,000,000
consumedTokens: 12,000
remaining: 988,000
status: active
expiresAt: 2026-11-29T23:00:00.000Z
This was the key verification point.
The data wasn't missing. The API route and controller logic were also correct. The problem was the environment/configuration used during the diagnostic process.
Final production verification
After restarting the PM2 process:
pm2 flush myzubster
pm2 restart myzubster --update-env
the application remained online:
status: online
script path: /root/myzubster/server.js
The health endpoint returned successfully:
{
"status": "ok",
"timestamp": "2026-08-16T06:33:25.195Z",
"uptime": 18.952552298
}
And the AI balance endpoint finally returned:
{
"success": true,
"userId": "DanielIoni-creator",
"model": "deepseek-chat",
"totalRemaining": 988000,
"contracts": [
{
"id": "6a7fe1a8eba8e2f854ea2eb3",
"remaining": 988000,
"expiresAt": "2026-11-29T23:00:00.000Z"
}
]
}
What this debugging session reinforced
A few simple practices made the difference:
Check the filesystem before creating new modules.
A missinggeocodeRoutes.jsturned out to be an existingmapRoutes.js.Don't duplicate existing routes.
The health endpoints already existed insrc/api/routes.js.Separate application errors from diagnostic-script errors.
A standalone script failing becauseMONGO_URIwas undefined did not necessarily mean the running application had the same problem.Inspect the actual database state.
Before changing business logic, verify whether the expected records exist.Test through the real HTTP endpoint.
The finalcurlrequest was the most important verification because it tested the complete chain:
HTTP → Express → route → controller → Mongoose → MongoDB → JSON response
Final result
The MyZubster backend is now loading correctly under PM2, MongoDB is connected, the health endpoints respond successfully, and the AI forwarding balance endpoint correctly reports:
988,000 remaining tokens.
What initially looked like an application/database problem ultimately came down to a combination of route-path mismatches and environment-variable consistency.
For me, the biggest takeaway is simple: before rewriting logic, verify the filesystem, environment, database, and actual HTTP response one layer at a time.
Top comments (0)