diff --git a/docs/DEPLOYMENT_TROUBLESHOOTING.md b/docs/DEPLOYMENT_TROUBLESHOOTING.md new file mode 100644 index 00000000..2ef7265b --- /dev/null +++ b/docs/DEPLOYMENT_TROUBLESHOOTING.md @@ -0,0 +1,93 @@ +# Deployment Troubleshooting Guide + +## Known Issues & Solutions + +### 1. Database Password with Special Characters in DATABASE_URL + +**Problem**: When the database password contains special characters (especially `%`), the backend container fails to connect with: +``` +sqlalchemy.exc.OperationalError: (psycopg.OperationalError) connection failed: + FATAL: password authentication failed for user "postgres" +``` + +**Root Cause**: The `DATABASE_URL` uses URL encoding. When the password contains `%`, the URL parser interprets it as a URL-encoded character. For example, `%81` gets decoded as a single byte instead of the literal characters `%81`. + +**Example**: +- Original password: `zmfCSR%816709301` +- In docker-compose.yml `POSTGRES_PASSWORD`: use **exact** password: `zmfCSR%816709301` +- In `DATABASE_URL`: must URL-encode the `%` as `%25`: `zmfCSR%25816709301` + +**Solution**: +```yaml +# docker-compose.server.yml +environment: + POSTGRES_PASSWORD: zmfCSR%816709301 # Exact password for postgres + DATABASE_URL: postgresql+psycopg://postgres:zmfCSR%25816709301@postgres:5432/ai_contract_platform +``` + +**Rule of thumb**: Any `%` in a URL must be written as `%25`. This applies to `DATABASE_URL`, `REDIS_URL`, and any other URL-based configuration. + +**Quick fix command** (on server): +```bash +cd /opt/ai-contract-platform +# Stop backend +docker compose -f docker-compose.server.yml stop backend +# Fix DATABASE_URL: replace % with %25 in docker-compose.server.yml +sed -i 's|zmfCSR%816709301|zmfCSR%25816709301|g' docker-compose.server.yml +# Verify +grep DATABASE_URL docker-compose.server.yml +# Restart +docker compose -f docker-compose.server.yml up -d backend +``` + +### 2. Missing Template Files at Startup + +**Problem**: Backend crashes on startup with: +``` +FileNotFoundError: [Errno 2] No such file or directory: + '/project-docs/phase13-legal-knowledge-template-library/contract-templates/...' +``` + +**Root Cause**: Docker build doesn't include `project-docs/` directory. The `template_service.py` tries to load template markdown files at import time. + +**Solution**: Fixed in commit `323e7cf`. The `_load_phase13_template_asset` function now: +1. Returns `None` if source files are missing +2. Filters out `None` entries from `DEFAULT_TEMPLATES` at module load time + +### 3. Missing `_context` Method in RemoteSharedAIPlatformClient + +**Problem**: Chat API returns 500 error: +``` +AttributeError: 'RemoteSharedAIPlatformClient' object has no attribute '_context' +``` + +**Root Cause**: The `RemoteSharedAIPlatformClient` class uses `self._context(current_user)` in many methods, but the method was never defined. + +**Solution**: Fixed in commit `3ff384c`. Added the `_context` method: +```python +def _context(self, current_user: Dict[str, Any]) -> SharedAIRequestContext: + return SharedAIRequestContext( + tenant_id=current_user.get("tenant_id", ""), + user_id=current_user.get("id", ""), + user_role=current_user.get("role", "admin"), + ) +``` + +## Deployment Checklist + +1. **Verify password encoding**: Check `DATABASE_URL` in `docker-compose.server.yml` has `%` encoded as `%25` +2. **Pull latest code**: `git pull origin main` +3. **Clean rebuild**: `docker compose -f docker-compose.server.yml down && docker compose -f docker-compose.server.yml up -d --build` +4. **Wait for postgres**: The `backend` container depends on `postgres` health check (up to 20 retries) +5. **Verify**: `curl -s http://localhost:8001/health` should return `{"status":"ok"}` + +## Server Information + +- **Server**: 192.168.3.90 +- **Project directory**: `/opt/ai-contract-platform` +- **SSH key**: `~/.ssh/water_audit_ed25519` +- **SSH user**: `root` +- **Gitea**: http://192.168.3.90:3000 +- **Frontend**: http://192.168.3.90:3003 +- **Backend API**: http://192.168.3.90:8001 +- **Database password**: `zmfCSR%816709301` (use `%25` in URLs)