| name | backend-debugging |
| description | Debug backend runtime errors (500s, crashes, unexpected behavior). Use when something is broken at runtime — not for writing new code. |
Backend Debugging
Step 0 — If it's a regression, check git history first
When the user reports "it worked before X" / "broke after the refactoring" / "used to work" — read the git history of the affected code path before proposing any fix. A defensive try/catch or null check is the wrong opening move on a regression; the bug is almost always something a recent commit dropped (a break, a return, a case arm, a relation in a query).
git log --oneline -20 -- <path/to/handler.ts>
git show <commit>:<path/to/handler.ts>
git log -p -5 -- <path/to/handler.ts>
The fix is then "restore what was lost," not "patch around the symptom." Only after you have the diff against the working version should you consider defensive code.
Step 1 — Read the logs
Before reading code, guessing, or querying the database, check the backend logs:
./dev logs backend
./dev logs --tail 200 backend
cat .dev/slot-$(cat .dev/slot)/backend.log
The logs contain full stack traces with file names and line numbers. This tells you exactly what's broken — no guessing needed.
Do not skip this step. Code review without the actual error is guesswork.
Step 2 — Reproduce the error
Confirm the error independently with curl. This isolates whether the problem is backend vs. frontend vs. CORS:
curl -s -c /tmp/cookies.txt http://localhost:3020/api/auth/login \
-X POST -H 'Content-Type: application/json' \
-d '{"email":"...","password":"..."}'
curl -s -b /tmp/cookies.txt "http://localhost:3020/api/..." | head -50
Replace port 3020 with whatever the current slot uses. Check with ./dev status.
Recognizing CORS errors
If the browser console shows "blocked by CORS policy" but the request returns a valid status code (e.g., 201), the backend works — the browser is rejecting the response. Look for:
- Hardcoded
Access-Control-Allow-Origin headers in the controller that override the global CORS middleware
- The global CORS config in
src/main.ts — in development mode (NODE_ENV !== 'production') it should allow all origins
Step 3 — Go to the error location
The stack trace gives you the exact file and line. Read that code. Common patterns:
"Cannot read properties of undefined (reading 'map')"
A relation wasn't loaded by TypeORM but the mapper assumes it's always present. Fix with optional chaining:
items.map(x => ...)
items?.map(x => ...) ?? []
This is especially common when:
- A
findAll query doesn't load the same relations as findOne
- Eager relations don't cascade through deeply nested joins (e.g.,
thread → sourceAssignments → source → details → contentChunks)
"Invalid source type" / "Invalid message role"
A mapper's instanceof or switch doesn't cover all cases. Check what the database actually contains:
cd ayunis-core-backend
pnpm exec ts-node -r tsconfig-paths/register -e "
import './src/config/env';
import { DataSource } from 'typeorm';
// ... query the relevant table
"
Step 4 — Fix, verify, check logs again
- Make the fix
- Wait for
nest --watch to reload (or check ./dev logs backend for compilation errors)
- Re-run the curl command from Step 2
- Check
./dev logs backend to confirm no new errors
- Run the validation sequence:
cd ayunis-core-backend
pnpm run lint && pnpm exec tsc --noEmit && pnpm run test