fix(admin): force fresh API requests to prevent cached 500 errors
- Add cache: 'no-store' to all apiCall functions in admin JS files - Prevents browser fetch cache from serving stale error responses - Addresses submissions endpoint 500 errors that weren't appearing in server logs - Killed duplicate server process (PID 1583625) - Added debug logging to submissions controller - Files modified: blog-validation.js, blog-curation.js, blog-curation-enhanced.js
This commit is contained in:
parent
6011a50042
commit
f7d0b68d39
6 changed files with 128 additions and 0 deletions
BIN
Screenshot from 2025-10-24 10-45-47.png
Normal file
BIN
Screenshot from 2025-10-24 10-45-47.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
124
TECHNICAL_BRIEF_SUBMISSIONS_500_ERROR.md
Normal file
124
TECHNICAL_BRIEF_SUBMISSIONS_500_ERROR.md
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Technical Brief: Submissions Endpoint 500 Errors
|
||||||
|
|
||||||
|
**Date**: 2025-10-24
|
||||||
|
**Severity**: High
|
||||||
|
**Status**: Unresolved after 1 hour investigation
|
||||||
|
|
||||||
|
## Problem Summary
|
||||||
|
|
||||||
|
Browser reports consistent 500 Internal Server Errors on submissions endpoints:
|
||||||
|
- `GET /api/submissions?limit=100` → 500 error
|
||||||
|
- `GET /api/submissions/by-blog-post/{id}` → 500 error
|
||||||
|
|
||||||
|
**Critical Finding**: Server logs show **ZERO** record of these 500 errors. Browser Network tab confirms requests to `http://localhost:9000`, but server stdout/stderr logs have no matching ERROR entries.
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
### Browser Behavior
|
||||||
|
- Network tab shows: `http://localhost:9000/api/submissions?limit=100` Status: 500
|
||||||
|
- Other endpoints work fine: `/api/blog/admin/posts` returns 200
|
||||||
|
- User is authenticated (other admin endpoints succeed)
|
||||||
|
|
||||||
|
### Server Behavior
|
||||||
|
- Server running on port 9000 (PID verified via `lsof -i:9000`)
|
||||||
|
- Started at 10:40:24 with latest code (commit 28ab839 from 10:31:19)
|
||||||
|
- Logs show NO 500 errors for submissions endpoints
|
||||||
|
- Only shows 401 (from curl test with expired token)
|
||||||
|
|
||||||
|
### Code Status
|
||||||
|
All fixes committed and deployed:
|
||||||
|
- ✅ Mongoose duplicate index warnings fixed (3 instances in Analytics.model.js)
|
||||||
|
- ✅ BlogPost `.populate()` calls removed from submissions controller
|
||||||
|
- ✅ User `.populate()` calls removed from submissions controller
|
||||||
|
- ✅ Code on disk verified correct (no populate calls present)
|
||||||
|
|
||||||
|
## Root Cause Hypothesis
|
||||||
|
|
||||||
|
**Service Worker Cache Poisoning**: The browser's service worker (`/public/service-worker.js`) may have cached the 500 error responses from earlier failed requests. Even after server restart with fixed code, the service worker serves stale error responses.
|
||||||
|
|
||||||
|
### Supporting Evidence
|
||||||
|
1. Browser shows errors but server has no log of requests
|
||||||
|
2. Cache version was bumped to `0.1.1` but service worker may not have updated
|
||||||
|
3. Service worker intercepts fetch requests before they reach server
|
||||||
|
|
||||||
|
## Immediate Actions Required
|
||||||
|
|
||||||
|
### Option 1: Clear Service Worker (User Action)
|
||||||
|
1. Open DevTools → Application tab → Service Workers
|
||||||
|
2. Click "Unregister" for localhost:9000
|
||||||
|
3. Hard reload (Ctrl+Shift+R)
|
||||||
|
|
||||||
|
### Option 2: Disable Service Worker (Code Change)
|
||||||
|
```javascript
|
||||||
|
// public/service-worker.js - Add at top
|
||||||
|
self.addEventListener('install', () => {
|
||||||
|
self.skipWaiting();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then(cacheNames => {
|
||||||
|
return Promise.all(
|
||||||
|
cacheNames.map(cacheName => caches.delete(cacheName))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: Debug Actual Error (If not cache)
|
||||||
|
If service worker is not the cause, the 500 errors ARE happening but error handling is swallowing them. Check:
|
||||||
|
|
||||||
|
**src/controllers/submissions.controller.js lines 76-129 (getSubmissions function)**:
|
||||||
|
```javascript
|
||||||
|
try {
|
||||||
|
// Query logic
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Submissions] Get submissions error:', error); // ← Should log
|
||||||
|
res.status(500).json({ success: false, error: 'Failed to fetch submissions' });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If logs truly show nothing, then:
|
||||||
|
- Error occurs BEFORE Morgan logging middleware
|
||||||
|
- Or try/catch is returning 500 without logging
|
||||||
|
- Or there's error-handling middleware intercepting
|
||||||
|
|
||||||
|
## Investigation Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if service worker is active
|
||||||
|
curl -I http://localhost:9000/service-worker.js
|
||||||
|
|
||||||
|
# Test endpoint with verbose logging
|
||||||
|
NODE_DEBUG=http node src/server.js 2>&1 | tee /tmp/debug-server.log
|
||||||
|
|
||||||
|
# Monitor in real-time
|
||||||
|
tail -f /tmp/fresh-server.log | grep -E "(submissions|500|ERROR)"
|
||||||
|
|
||||||
|
# Check all Node processes
|
||||||
|
ps aux | grep "node.*server.js"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Files Modified (Session History)
|
||||||
|
|
||||||
|
1. `src/models/Analytics.model.js` - Removed 3 duplicate index definitions
|
||||||
|
2. `src/controllers/submissions.controller.js` - Removed BlogPost and User populate calls
|
||||||
|
3. `src/models/SubmissionTracking.model.js` - Removed BlogPost populate from static methods
|
||||||
|
4. `public/version.json` - Bumped to 0.1.1
|
||||||
|
5. `public/service-worker.js` - Updated CACHE_VERSION to 0.1.1
|
||||||
|
|
||||||
|
## Next Steps for External Auditor
|
||||||
|
|
||||||
|
1. **Verify service worker status** in browser DevTools
|
||||||
|
2. **Check MongoDB connection** - submissions controller uses `SubmissionTracking.find()`
|
||||||
|
3. **Add explicit logging** at top of getSubmissions function to confirm it's being called
|
||||||
|
4. **Check middleware stack** in `src/routes/submissions.routes.js` - auth middleware may be failing silently
|
||||||
|
5. **Inspect error-handling middleware** in `src/server.js` - may be catching errors before logging
|
||||||
|
|
||||||
|
## Contact
|
||||||
|
|
||||||
|
- Project: Tractatus Website (tractatus-website)
|
||||||
|
- Database: MongoDB tractatus_dev (port 27017)
|
||||||
|
- Server: Node.js/Express (port 9000)
|
||||||
|
- Session context: Previous work on Mongoose warnings + submissions tracking
|
||||||
|
|
@ -15,6 +15,7 @@ function getAuthToken() {
|
||||||
async function apiCall(endpoint, options = {}) {
|
async function apiCall(endpoint, options = {}) {
|
||||||
const token = getAuthToken();
|
const token = getAuthToken();
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
|
cache: 'no-store', // Force fresh requests - prevent cached 500 errors
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ function checkAuth() {
|
||||||
async function apiCall(endpoint, options = {}) {
|
async function apiCall(endpoint, options = {}) {
|
||||||
const token = getAuthToken();
|
const token = getAuthToken();
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
|
cache: 'no-store', // Force fresh requests - prevent cached 500 errors
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ function getAuthToken() {
|
||||||
async function apiCall(endpoint, options = {}) {
|
async function apiCall(endpoint, options = {}) {
|
||||||
const token = getAuthToken();
|
const token = getAuthToken();
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
|
cache: 'no-store', // Force fresh requests - prevent cached 500 errors
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ async function createSubmission(req, res) {
|
||||||
* Get all submissions with optional filtering
|
* Get all submissions with optional filtering
|
||||||
*/
|
*/
|
||||||
async function getSubmissions(req, res) {
|
async function getSubmissions(req, res) {
|
||||||
|
console.log('[SUBMISSIONS DEBUG] getSubmissions called, query:', req.query);
|
||||||
try {
|
try {
|
||||||
const { status, publicationId, limit = 50, offset = 0 } = req.query;
|
const { status, publicationId, limit = 50, offset = 0 } = req.query;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue