Debugging Runbook - MyTelevision API
Purpose: Guide for diagnosing and resolving common issues in the MyTelevision API.
Table of Contents
- Quick Diagnostics
- Application Issues
- Database Issues
- Redis/Cache Issues
- Authentication Issues
- Performance Issues
- Docker/Deployment Issues
- API-Specific Issues
Quick Diagnostics
Health Check Commands
# API Health
curl http://localhost:3000/api/v2/health/live
curl http://localhost:3000/api/v2/health/ready
# Database connectivity
npx prisma db pull --force
# Redis connectivity
redis-cli ping
# Docker status
docker-compose ps
docker-compose logs --tail=50 api
Common Environment Issues
# Check environment variables are loaded
node -e "console.log(process.env.DATABASE_URL ? 'DB_URL: Set' : 'DB_URL: MISSING')"
node -e "console.log(process.env.JWT_SECRET ? 'JWT: Set' : 'JWT: MISSING')"
node -e "console.log(process.env.REDIS_PASSWORD ? 'REDIS: Set' : 'REDIS: MISSING')"
# Validate environment
npm run build # Will fail if critical env vars missing
Application Issues
1. Application Won't Start
Symptoms: Error: Cannot find module, EADDRINUSE, startup crashes
Debug Steps:
# 1. Check for port conflicts
netstat -tulpn | grep 3000
# or on Windows:
netstat -ano | findstr :3000
# 2. Verify dependencies
rm -rf node_modules
npm ci
# 3. Regenerate Prisma client
npm run prisma:generate
# 4. Check TypeScript compilation
npm run build
# 5. Run with verbose logging
DEBUG=* npm run start:dev
2. Module Resolution Errors
Symptoms: Cannot resolve @infrastructure/..., path alias errors
Fix:
# Verify tsconfig paths
cat tsconfig.json | grep -A 20 "paths"
# Ensure baseUrl is set
# "baseUrl": "./",
# "paths": {
# "@/*": ["src/*"],
# "@infrastructure/*": ["src/infrastructure/*"],
# ...
# }
# Rebuild
npm run build
3. Validation Pipe Errors
Symptoms: 400 Bad Request with cryptic messages
Debug:
// Add detailed validation error logging
// In main.ts, update ValidationPipe:
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
exceptionFactory: (errors) => {
console.error('Validation errors:', JSON.stringify(errors, null, 2));
return new BadRequestException(errors);
},
}),
);
Database Issues
1. Connection Errors
Symptoms: P1001: Can't reach database server, connection timeout
Debug:
# 1. Verify PostgreSQL is running
docker-compose ps postgres
docker-compose logs postgres --tail=20
# 2. Test connection manually
psql postgresql://mytelevision:mytelevision_secret@localhost:5432/mytelevision
# 3. Check DATABASE_URL format
echo $DATABASE_URL
# Expected: postgresql://user:password@host:port/database?schema=public
# 4. Verify network (Docker)
docker network ls
docker network inspect mytelevision-network
# 5. Check firewall
sudo ufw status
2. Migration Errors
Symptoms: P3006: Migration failed, schema drift
Debug:
# 1. Check migration status
npx prisma migrate status
# 2. Reset database (DEVELOPMENT ONLY!)
npx prisma migrate reset
# 3. Generate migration from schema changes
npx prisma migrate dev --name describe_your_changes
# 4. Apply pending migrations
npx prisma migrate deploy
# 5. If stuck, force resolve
npx prisma migrate resolve --applied "migration_name"
3. Query Performance
Symptoms: Slow API responses, timeout errors
Debug:
# 1. Enable Prisma query logging
# In .env:
# DEBUG=prisma:query
# 2. Check slow queries in PostgreSQL
SELECT query, calls, mean_time, total_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
# 3. Analyze specific query
EXPLAIN ANALYZE SELECT * FROM "Movie" WHERE status = 'PUBLISHED' LIMIT 10;
# 4. Check missing indexes
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
WHERE seq_scan > idx_scan
ORDER BY seq_scan DESC;
4. Prisma Client Issues
Symptoms: Type errors, outdated client
Fix:
# Regenerate client
npm run prisma:generate
# If types still wrong, clear cache
rm -rf node_modules/.prisma
npm run prisma:generate
# Verify client version matches
npx prisma version
Redis/Cache Issues
1. Connection Errors
Symptoms: ECONNREFUSED, NOAUTH
Debug:
# 1. Verify Redis is running
docker-compose ps redis
docker-compose logs redis --tail=20
# 2. Test connection
redis-cli -a ${REDIS_PASSWORD} ping
# 3. Check connection details
redis-cli -a ${REDIS_PASSWORD} INFO server
# 4. Verify password matches
echo $REDIS_PASSWORD
2. Cache Inconsistency
Symptoms: Stale data, cache not updating
Debug:
# 1. Check specific cache key
redis-cli -a ${REDIS_PASSWORD} GET "cache:movies:list:page1"
# 2. Check TTL
redis-cli -a ${REDIS_PASSWORD} TTL "cache:movies:list:page1"
# 3. Clear specific cache pattern
redis-cli -a ${REDIS_PASSWORD} KEYS "cache:movies:*" | xargs redis-cli -a ${REDIS_PASSWORD} DEL
# 4. Clear all cache (careful!)
redis-cli -a ${REDIS_PASSWORD} FLUSHDB
3. Memory Issues
Symptoms: Redis OOM, eviction warnings
Debug:
# 1. Check memory usage
redis-cli -a ${REDIS_PASSWORD} INFO memory
# 2. Find large keys
redis-cli -a ${REDIS_PASSWORD} --bigkeys
# 3. Check eviction policy
redis-cli -a ${REDIS_PASSWORD} CONFIG GET maxmemory-policy
# 4. Set memory limit
redis-cli -a ${REDIS_PASSWORD} CONFIG SET maxmemory 256mb
redis-cli -a ${REDIS_PASSWORD} CONFIG SET maxmemory-policy allkeys-lru
Authentication Issues
1. JWT Errors
Symptoms: invalid token, jwt expired, jwt malformed
Debug:
# 1. Decode JWT (without verification)
# Install: npm install -g jwt-cli
jwt decode <TOKEN>
# 2. Check token structure
echo "<TOKEN>" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq
# 3. Verify JWT_SECRET is set
node -e "console.log('JWT_SECRET:', process.env.JWT_SECRET?.substring(0,10) + '...')"
# 4. Check token expiration
# In the decoded payload, check "exp" field
# Convert: date -d @<exp_timestamp>
2. Session Not Found
Symptoms: 401 after login, session invalidated
Debug:
# 1. Check session exists in Redis
redis-cli -a ${REDIS_PASSWORD} KEYS "session:*"
# 2. Check session in database
SELECT * FROM "UserSession" WHERE "userId" = '<USER_ID>' ORDER BY "createdAt" DESC LIMIT 5;
SELECT * FROM "AccountSession" WHERE "accountId" = '<ACCOUNT_ID>' ORDER BY "createdAt" DESC LIMIT 5;
# 3. Verify token hash matches
# The stored token is hashed with SHA256
node -e "const crypto = require('crypto'); console.log(crypto.createHash('sha256').update('<TOKEN>').digest('hex'))"
3. Rate Limiting Issues
Symptoms: 429 Too Many Requests
Debug:
# 1. Check rate limit counters
redis-cli -a ${REDIS_PASSWORD} KEYS "throttle:*"
# 2. Get specific counter
redis-cli -a ${REDIS_PASSWORD} GET "throttle:short:<IP>"
# 3. Check TTL
redis-cli -a ${REDIS_PASSWORD} TTL "throttle:short:<IP>"
# 4. Clear rate limit for IP (testing only)
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:short:<IP>"
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:medium:<IP>"
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:long:<IP>"
Performance Issues
1. Slow API Responses
Debug:
# 1. Profile endpoint
time curl -w "@curl-format.txt" -o /dev/null http://localhost:3000/api/v2/movies
# curl-format.txt contents:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_appconnect: %{time_appconnect}\n
# time_pretransfer: %{time_pretransfer}\n
# time_redirect: %{time_redirect}\n
# time_starttransfer: %{time_starttransfer}\n
# ----------\n
# time_total: %{time_total}\n
# 2. Check Node.js memory
node -e "console.log(process.memoryUsage())"
# 3. Profile CPU usage
node --prof dist/main.js
# Then analyze:
node --prof-process isolate-*.log > profile.txt
2. Memory Leaks
Debug:
# 1. Take heap snapshot
node --inspect dist/main.js
# Connect Chrome DevTools: chrome://inspect
# 2. Monitor memory over time
while true; do
curl -s http://localhost:3000/api/v2/health/live | jq '.memory'
sleep 60
done
# 3. Check for event listener leaks
node -e "require('events').defaultMaxListeners = 10; process.on('warning', (w) => console.warn(w));"
3. Database Connection Pool Exhaustion
Symptoms: Connection timeout after prolonged use
Debug:
-- Check active connections
SELECT count(*) FROM pg_stat_activity WHERE datname = 'mytelevision';
-- See what's using connections
SELECT pid, usename, application_name, client_addr, state, query
FROM pg_stat_activity
WHERE datname = 'mytelevision';
-- Kill idle connections (careful!)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mytelevision'
AND state = 'idle'
AND query_start < NOW() - INTERVAL '10 minutes';
Docker/Deployment Issues
1. Container Won't Start
Debug:
# 1. Check container logs
docker-compose logs api --tail=100
# 2. Check container status
docker-compose ps
docker inspect mytelevision-api
# 3. Check resource limits
docker stats mytelevision-api
# 4. Shell into container
docker exec -it mytelevision-api /bin/sh
# 5. Rebuild from scratch
docker-compose down -v
docker-compose build --no-cache
docker-compose up -d
2. Network Issues
Debug:
# 1. Check network
docker network inspect mytelevision-network
# 2. Test inter-container connectivity
docker exec mytelevision-api ping postgres
docker exec mytelevision-api ping redis
# 3. Check DNS resolution
docker exec mytelevision-api nslookup postgres
3. Volume/Data Persistence
Debug:
# 1. List volumes
docker volume ls | grep mytelevision
# 2. Inspect volume
docker volume inspect mytelevision-api_postgres_data
# 3. Backup volume
docker run --rm -v mytelevision-api_postgres_data:/data -v $(pwd):/backup alpine tar cvf /backup/postgres_backup.tar /data
# 4. Check volume mount
docker inspect mytelevision-postgres | jq '.[0].Mounts'
API-Specific Issues
1. Streaming Token Issues
Symptoms: Invalid stream token, expired token
Debug:
# 1. Generate test stream token
curl -X POST http://localhost:3000/api/v2/streaming/token \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"mediaType": "MOVIE", "contentId": "123"}'
# 2. Verify token
curl -X POST http://localhost:3000/api/v2/streaming/verify \
-H "X-Stream-Token: <STREAM_TOKEN>"
# 3. Check signing secret
node -e "console.log('STREAMING_SIGNING_SECRET:', process.env.STREAMING_SIGNING_SECRET?.substring(0,10) + '...')"
2. TMDb Integration
Symptoms: Movie autofill not working
Debug:
# 1. Test TMDb API directly
curl "https://api.themoviedb.org/3/movie/550?api_key=${TMDB_API_KEY}&language=fr-FR"
# 2. Check API key
node -e "console.log('TMDB_API_KEY:', process.env.TMDB_API_KEY ? 'Set' : 'MISSING')"
# 3. Test search
curl "https://api.themoviedb.org/3/search/movie?api_key=${TMDB_API_KEY}&query=Matrix"
3. i18n/Localization
Symptoms: Wrong language returned
Debug:
# 1. Test with Accept-Language header
curl -H "Accept-Language: en-US" http://localhost:3000/api/v2/movies/1
# 2. Test with query parameter
curl "http://localhost:3000/api/v2/movies/1?lang=en_US"
# 3. Check response header
curl -I http://localhost:3000/api/v2/movies/1 | grep Content-Language
# 4. Verify translation files exist
ls -la src/resources/i18n/
Useful Commands Reference
# Restart everything
docker-compose restart
# View real-time logs
docker-compose logs -f api
# Check disk space
df -h
# Check memory
free -m
# Kill stuck process
pkill -f "node dist/main"
# Prisma studio (GUI)
npx prisma studio
# Generate types
npm run prisma:generate
# Run specific test
npm test -- --testPathPattern="auth"
# Check for outdated packages
npm outdated
# Security audit
npm audit