Troubleshooting Guide

Diagnose and resolve common issues with the Vantrexia platform

Common Issues

Click on any issue below to expand the diagnosis steps and resolution.

Cause: Vantrexia enforces rate limiting on login attempts. After 5 consecutive failed login attempts, the account is locked out for 30 minutes.

Resolution

  • Wait 30 minutes — The lockout expires automatically after the cooldown period.
  • Admin clear via API — An administrator can immediately unlock the account:
    HTTP
    POST /api/v1/auth/clear-lockout/
    Content-Type: application/json
    Authorization: Bearer <admin_token>
    
    {
      "email": "user@practice.com"
    }
  • Admin clear via CLI:
    Shell
    docker-compose exec backend python manage.py clear_lockout user@practice.com
Prevention

If users frequently lock themselves out, consider enabling SSO/SAML integration or implementing a "Forgot Password" self-service flow.

Cause: The eCW FHIR integration can fail due to authentication issues, expired tokens, or incorrect scopes.

Diagnosis Steps

  1. Check eCW auth status — Navigate to Admin > Integrations > eClinicalWorks and verify the connection status shows "Connected".
  2. Verify JWKS endpoint — Ensure the JWKS URL is accessible:
    Shell
    curl -s https://oauthserver.eclinicalworks.com/oauth/jwks | python -m json.tool
  3. Check token expiry — eCW tokens expire after 60 minutes. Verify the refresh token mechanism is working:
    Shell
    docker-compose logs backend | grep "ecw_token\|token_refresh\|401"
  4. Verify FHIR scopes — The integration requires these scopes: system/Patient.read, system/Observation.write. Check the scopes granted in the eCW admin portal.

Cause: Observations may fail at the processing pipeline due to validation errors, unsupported vital types, or webhook delivery issues.

Diagnosis Steps

  1. Check the observation processing pipeline:
    Shell
    docker-compose logs backend | grep "observation\|vital\|processing" | tail -20
  2. Verify vital type support — Vantrexia supports: blood_pressure, weight, blood_glucose, pulse_oximetry. Other vital types are logged but not processed.
  3. Check for validation errors — Look for rejected observations:
    Shell
    docker-compose exec backend python manage.py shell -c "
    from apps.core.models import ObservationError
    errors = ObservationError.objects.order_by('-created_at')[:10]
    for e in errors:
        print(f'{e.created_at}: {e.error_type} - {e.message}')
    "
  4. Verify the patient exists — Observations for unknown patient IDs are queued for retry. Check the patient mapping table.

Cause: Billing entries may show $0 when CPT code mappings are incorrect, the payer is not configured, or time thresholds have not been met.

Diagnosis Steps

  1. Verify CPT code mappings — Navigate to Admin > Billing > CPT Configuration and ensure rates are set for:
    • 99453 — Device setup & patient education
    • 99454 — Device supply, daily monitoring
    • 99457 — First 20 minutes clinical time per month
    • 99458 — Each additional 20 minutes
  2. Check payer configuration — Ensure the patient's insurance payer is configured with reimbursement rates in the payer table.
  3. Verify monitoring time thresholds — CPT 99457 requires a minimum of 20 minutes of clinical monitoring time per month. Check the patient's logged time:
    Shell
    docker-compose exec backend python manage.py shell -c "
    from apps.core.models import MonitoringTime
    from apps.core.models import Patient
    p = Patient.objects.get(id='patient_id_here')
    mt = MonitoringTime.objects.filter(patient=p, month='2026-02').first()
    print(f'Total time: {mt.total_minutes} minutes' if mt else 'No time logged')
    "

Cause: Push notification failures can result from invalid FCM tokens, device registration issues, or permission denials on the device.

Diagnosis Steps

  1. Check FCM token validity — Tokens can become invalid when users reinstall the app or clear app data:
    Shell
    docker-compose logs celery | grep "FCM\|firebase\|notification" | tail -20
  2. Verify device registration — Ensure the user's device is registered in the push notifications table.
  3. Check notification permissions — The user must grant notification permissions in their device settings (iOS: Settings > Vantrexia > Notifications; Android: Settings > Apps > Vantrexia > Notifications).
  4. Verify FCM credentials — Ensure the FIREBASE_CREDENTIALS environment variable points to a valid service account JSON file.

Cause: Container startup failures are usually caused by missing configuration, port conflicts, or insufficient system resources.

Diagnosis Steps

  1. Check Docker Compose logs:
    Shell
    docker-compose logs --tail=50
  2. Verify .env file exists — All containers depend on environment variables. Ensure .env exists in the project root:
    ls -la .env
  3. Check port conflicts — Default ports: 8000 (backend), 3000 (frontend), 5432 (PostgreSQL), 6379 (Redis):
    lsof -i :8000 -i :3000 -i :5432 -i :6379
  4. Verify Docker resources — Vantrexia requires at least 4 GB RAM allocated to Docker. Check in Docker Desktop > Settings > Resources.
  5. Clean restart:
    Shell
    docker-compose down -v
    docker system prune -f
    docker-compose up -d --build

Cause: SSL errors typically indicate expired certificates, misconfigured Cloudflare settings, or domain mismatches in nginx.

Diagnosis Steps

  1. Verify Cloudflare origin certificate — Check the certificate in Cloudflare > SSL/TLS > Origin Server. Ensure it hasn't expired.
  2. Check certificate expiry:
    Shell
    echo | openssl s_client -connect api.yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates
  3. Ensure correct domain in nginx.conf — The server_name directive must match your actual domain:
    grep server_name docker/nginx/nginx.conf
  4. Verify SSL mode — If using Cloudflare, set SSL mode to Full (Strict) and ensure the origin certificate is installed on the server.

Cause: Celery task failures are usually caused by Redis connection issues, worker crashes, or misconfigured beat schedules.

Diagnosis Steps

  1. Check Redis connection:
    Shell
    docker-compose exec redis redis-cli ping
    # Expected: PONG
  2. Verify Celery worker is running:
    docker-compose ps celery celery-beat
  3. Check Celery logs:
    docker-compose logs celery --tail=30
  4. Check Celery beat schedule — Verify periodic tasks are registered:
    Shell
    docker-compose exec backend python manage.py shell -c "
    from django_celery_beat.models import PeriodicTask
    for task in PeriodicTask.objects.filter(enabled=True):
        print(f'{task.name}: {task.task} ({task.schedule})')
    "
  5. Restart Celery services:
    docker-compose restart celery celery-beat

Reading Logs

Vantrexia uses structured JSON logging for all backend services. Here's how to access and interpret logs.

Log Locations

Service Log Location Access Command
Backend (Django) /logs/vantrexia.log docker-compose logs -f backend
Celery Worker /logs/celery.log docker-compose logs -f celery
Celery Beat /logs/celery-beat.log docker-compose logs -f celery-beat
Nginx /var/log/nginx/ docker-compose logs -f nginx
PostgreSQL /var/log/postgresql/ docker-compose logs -f postgres

Structured Log Format

All backend logs use a structured JSON format for easy parsing and analysis:

JSON — Example Log Entry
{
  "timestamp": "2026-02-09T14:30:22.456Z",
  "level": "ERROR",
  "logger": "apps.mio_integration",
  "message": "Webhook signature verification failed",
  "request_id": "req_abc123",
  "ip": "52.22.140.15",
  "path": "/api/v1/mio/webhook/",
  "extra": {
    "expected_prefix": "sha256=",
    "received_header": "none"
  }
}

Useful Log Filtering Commands

Shell — Common Log Queries
# Show only errors from the last hour
docker-compose logs --since=1h backend | grep '"level": "ERROR"'

# Filter by specific module
docker-compose logs backend | grep "apps.billing"

# Count errors by type
docker-compose logs backend 2>&1 | grep ERROR | wc -l

# Follow logs in real time (all services)
docker-compose logs -f --tail=0

Health Check Endpoints

Vantrexia exposes several health check endpoints for monitoring service status. These are used by load balancers, uptime monitors, and the deployment pipeline.

Endpoint Service Success Response Failure Response
GET /health/ Overall system health 200 {"status": "healthy"} 503 {"status": "unhealthy", "checks": {...}}
GET /health/db/ PostgreSQL database 200 {"database": "connected"} 503 {"database": "disconnected"}
GET /health/redis/ Redis cache & message broker 200 {"redis": "connected"} 503 {"redis": "disconnected"}
GET /health/celery/ Celery task queue 200 {"celery": "active", "workers": 2} 503 {"celery": "inactive", "workers": 0}
Shell — Quick Health Check
# Check all services at once
curl -s https://api.yourdomain.com/health/ | python -m json.tool

# Response when healthy:
{
  "status": "healthy",
  "checks": {
    "database": "connected",
    "redis": "connected",
    "celery": "active"
  },
  "version": "1.0.0",
  "uptime": "14d 6h 32m"
}
Monitoring Integration

These health check endpoints are designed to work with uptime monitoring services like UptimeRobot, Pingdom, or AWS CloudWatch. Configure your monitor to check /health/ every 60 seconds and alert on non-200 responses.

Debug Mode

Never Enable Debug in Production

NEVER set DEBUG=True in a production environment. Debug mode exposes sensitive information including stack traces, environment variables, database queries, and installed packages. It is a serious security vulnerability and HIPAA violation.

Enabling Debug Mode (Development Only)

Set the following in your .env file for local development:

.env
DEBUG=True
DEBUG_TOOLBAR=True
SQL_QUERY_LOGGING=True

Django Debug Toolbar

When DEBUG_TOOLBAR=True, the Django Debug Toolbar is available in the browser for HTML responses. It provides:

  • SQL Queries — See all database queries for the current request, with timing and EXPLAIN analysis
  • Cache — View cache hits/misses and cached values
  • Templates — Inspect template rendering context
  • Headers — View request/response headers
  • Profiling — CPU profiling for the current request

SQL Query Logging

When SQL_QUERY_LOGGING=True, all SQL queries are logged with execution time:

Log Output
[2026-02-09 14:30:22] SQL (2.3ms): SELECT * FROM patients_patient WHERE id = 'pat_abc123'
[2026-02-09 14:30:22] SQL (1.1ms): SELECT * FROM observations_observation WHERE patient_id = 'pat_abc123' ORDER BY -timestamp LIMIT 10
[2026-02-09 14:30:22] Total queries: 2 | Total time: 3.4ms

Getting Support

If the troubleshooting steps above don't resolve your issue, reach out through one of these channels:

Channel Details Response Time
GitHub Issues github.com/highlandpc/Vantrexia/issues 1–2 business days
Email Support support@vantrexia.com Same business day
Emergency Hotline For production outages only — contact details provided in your service agreement Within 1 hour
When Contacting Support

Include the following in your support request to help us resolve your issue faster:

  • Vantrexia version (cat VERSION)
  • Relevant log output (redact any PHI/PII)
  • Steps to reproduce the issue
  • Environment details (Docker version, OS, browser)
  • Health check output (curl /health/)