5.5 KiB
🐛 Available Users API 500 Error - Fixed
Issue
Error: 500 Internal Server Error
Endpoint: GET /api/members/users/available/:groupId
URL: https://chitfund.deepteklabs.com/api/members/users/available/d3ac73b2-305f-49c8-82d6-84076235f9c3
SQL Error: syntax error at or near "SELECT"
Root Cause
The SQL subquery in NOT IN clause was missing parentheses:
-- ❌ WRONG (Missing parentheses)
WHERE "User"."id" NOT IN
SELECT user_id FROM group_members ...
-- ✅ CORRECT (With parentheses)
WHERE "User"."id" NOT IN (
SELECT user_id FROM group_members ...
)
The Fix
File: backend/src/controllers/memberController.js
Before (Missing parentheses):
id: {
[Op.notIn]: require('sequelize').literal(`
SELECT user_id FROM group_members
WHERE group_id = '${groupId}' AND status = 'active'
`)
}
After (With parentheses):
const { sequelize } = require('../config/database');
id: {
[Op.notIn]: sequelize.literal(`(
SELECT user_id FROM group_members
WHERE group_id = '${groupId}' AND status = 'active'
)`)
}
Changes Made:
- ✅ Added parentheses around subquery:
(SELECT ...) - ✅ Imported sequelize from database config (cleaner)
What This Endpoint Does
Returns a list of users who are NOT already members of a specific chit group. Used when a manager wants to add new members to a group.
Request:
GET /api/members/users/available/:groupId?page=1&limit=50&search=john
Response:
{
"success": true,
"data": {
"users": [
{
"id": "uuid",
"full_name": "John Doe",
"mobile_number": "9876543210",
"email": "john@example.com",
"address": "123 Main St",
"emergency_contact": "9999999999",
"created_at": "2025-11-06T..."
}
],
"pagination": {
"currentPage": 1,
"totalPages": 1,
"totalItems": 5,
"itemsPerPage": 50
}
}
}
How to Deploy
# 1. Commit changes
git add backend/src/controllers/memberController.js
git commit -m "Fix available users API - add parentheses to subquery"
git push origin prodnew
# 2. Deploy to production
ssh luckychit@192.168.8.148
cd /home/luckychit/apps/chitfund
./scripts/deploy.sh backend
# 3. Test it works
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://chitfund.deepteklabs.com/api/members/users/available/YOUR_GROUP_ID"
Testing
Test 1: Get Available Users
curl -H "Authorization: Bearer MANAGER_TOKEN" \
"https://chitfund.deepteklabs.com/api/members/users/available/d3ac73b2-305f-49c8-82d6-84076235f9c3"
Should return: List of users not in the group
Test 2: With Search
curl -H "Authorization: Bearer MANAGER_TOKEN" \
"https://chitfund.deepteklabs.com/api/members/users/available/d3ac73b2-305f-49c8-82d6-84076235f9c3?search=john"
Should return: Filtered users matching "john"
Test 3: With Pagination
curl -H "Authorization: Bearer MANAGER_TOKEN" \
"https://chitfund.deepteklabs.com/api/members/users/available/d3ac73b2-305f-49c8-82d6-84076235f9c3?page=1&limit=10"
Should return: First 10 available users
SQL Syntax Rules
NOT IN with Subquery
Always wrap subquery in parentheses:
-- ✅ CORRECT
WHERE id NOT IN (
SELECT user_id FROM table
)
-- ❌ WRONG
WHERE id NOT IN
SELECT user_id FROM table
EXISTS Alternative (Better Performance)
For better performance, consider using NOT EXISTS:
// Alternative implementation (faster for large datasets)
id: {
[Op.notIn]: sequelize.literal(`(
SELECT gm.user_id
FROM group_members gm
WHERE gm.group_id = '${groupId}'
AND gm.status = 'active'
)`)
}
// Or using NOT EXISTS:
where: sequelize.literal(`
NOT EXISTS (
SELECT 1 FROM group_members gm
WHERE gm.user_id = "User"."id"
AND gm.group_id = '${groupId}'
AND gm.status = 'active'
)
`)
Security Note
⚠️ SQL Injection Risk: The current code uses string interpolation for groupId:
WHERE group_id = '${groupId}' // ⚠️ Vulnerable to SQL injection
Recommended Fix (Future):
Use Sequelize's replacements for safer queries:
id: {
[Op.notIn]: sequelize.literal(`(
SELECT user_id FROM group_members
WHERE group_id = :groupId AND status = 'active'
)`),
}
// Then use replacements in the query
{
replacements: { groupId },
type: sequelize.QueryTypes.SELECT
}
For now: The route is protected with requireManager middleware, so only authenticated managers can access it. Still, consider improving this for better security.
Related Endpoints
All working correctly:
- ✅
POST /api/members/:groupId/members- Add member to group - ✅
GET /api/members/:groupId/members- Get group members - ✅
GET /api/members/:groupId/members/:memberId- Get member details - ✅
PUT /api/members/:groupId/members/:memberId/status- Update member status
Summary
Problem: SQL syntax error - missing parentheses around NOT IN subquery
Solution: Added parentheses: NOT IN (SELECT ...)
Impact: Managers can now see available users to add to groups
Status: ✅ Fixed
Deploy: ./scripts/deploy.sh backend
Files Changed
backend/src/controllers/memberController.js✅ Fixed
The available users API should now work correctly! 🎉
Managers can now see which users are available to add to their chit groups.