> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prvue.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Common issues and solutions for Prvue

Common issues and solutions for Prvue.

## Setup Issues

### Terraform Errors

**Error: "Failed to initialize Terraform"**

* Ensure Terraform is installed: `terraform version`
* Check Terraform version >= 1.5.0
* Verify Digital Ocean token is valid

**Error: "Failed to create droplet"**

* Check Digital Ocean account has sufficient credits
* Verify region is available
* Check droplet size is available in selected region

**Error: "SSH connection failed"**

* Verify SSH public key is correct
* Check firewall allows SSH (port 22)
* Wait a few minutes for droplet to fully initialize

### Ansible Errors

**Error: "Failed to connect to host"**

* Ensure SSH access works: `ssh root@SERVER_IP`
* Check inventory file is correctly generated
* Verify SSH key is added to droplet

**Error: "Docker installation failed"**

* Check internet connectivity on droplet
* Verify Ubuntu 22.04 is being used
* Check Ansible logs for detailed error

**Error: "Orchestrator service failed to start"**

* Check environment variables are set correctly
* Verify Node.js is installed: `node --version`
* Check orchestrator logs: `journalctl -u preview-orchestrator -f`

## Deployment Issues

### Webhook Not Triggering

**Symptoms**: PR opened but no preview deployment

**Solutions**:

1. Check webhook is configured:

   ```bash theme={null}
   # Via GitHub API or web interface
   ```

2. Verify webhook secret matches:

   ```bash theme={null}
   cat ~/.preview-deployer/config.yml | grep webhook_secret
   ```

3. Check orchestrator logs:

   ```bash theme={null}
   ssh root@SERVER_IP
   journalctl -u preview-orchestrator -f
   ```

4. Test webhook manually:
   ```bash theme={null}
   curl -X POST http://SERVER_IP:3000/webhook/github \
     -H "Content-Type: application/json" \
     -H "X-Hub-Signature-256: sha256=..." \
     -d '{"action":"opened",...}'
   ```

### Missing or Invalid `preview-config.yml`

**Symptoms**: Deployment fails with "preview-config.yml is required at repository root but was not found" or a validation error (e.g. "framework is required", "health\_check\_path is not valid").

**Cause**: The orchestrator requires a valid `preview-config.yml` at the repository root. Required fields: `framework`, `database`, `health_check_path`, `app_port`, `app_port_env`, `app_entrypoint`.

**Solutions**:

1. Add `preview-config.yml` in the repo root (see [Configuration Reference](/configuration)).
2. Ensure all required fields are present and valid (e.g. `health_check_path` must start with `/`, `app_port` must be a positive number).
3. If the file exists but deployment still fails, check orchestrator logs for the exact validation message (e.g. invalid YAML or missing field).

### Build Failures

**Symptoms**: Preview deployment fails during build

**Solutions**:

1. Check Docker build logs:

   ```bash theme={null}
   ssh root@SERVER_IP
   # Work dir is {projectSlug}/pr-{PR_NUMBER} (e.g. myorg-myapp/pr-12)
   cd /opt/preview-deployments/{projectSlug}/pr-{PR_NUMBER}
   docker compose -p {deploymentId} logs app
   ```

2. Verify Dockerfile exists and is correct

3. Check build commands in `preview-config.yml`

4. Ensure dependencies are installable

#### `pnpm install --prod` fails (e.g. prepare script / husky)

**Symptoms**: Build fails at `RUN pnpm install --frozen-lockfile --prod` (or similar) with exit code 1.

**Cause**: Lifecycle scripts like `prepare` or `postinstall` in `package.json` can depend on devDependencies (e.g. **husky**). With `--prod`, devDependencies are not installed, so the script fails when it runs.

**Fixes (in your app or its Dockerfile)**:

* **Husky**: Set `ENV HUSKY=0` before the install step in your Dockerfile so the prepare script is a no-op in Docker/CI.
* **General**: Move the script's dependency to `dependencies` if it must run in production builds, or in the Dockerfile run install with `--ignore-scripts` and then run only the commands you need (e.g. build).
* **Prvue**: When the repo has no Dockerfile, we inject a default that sets `HUSKY=0` so this case is avoided for our template.

### Health Check Failures

**Symptoms**: Containers start but preview URL doesn't work

**Solutions**:

1. Verify health check endpoint exists:

   ```bash theme={null}
   curl http://localhost:{APP_PORT}/health
   ```

2. Check health check path in `preview-config.yml`:

   ```yaml theme={null}
   health_check_path: /health # Must match your app's endpoint
   ```

3. Check container logs:

   ```bash theme={null}
   docker logs {projectSlug}-pr-{PR_NUMBER}-app
   ```

4. Verify app is listening on correct port:
   ```bash theme={null}
   docker exec {projectSlug}-pr-{PR_NUMBER}-app netstat -tlnp
   ```

### Port Conflicts

**Symptoms**: "Port already in use" error

**Solutions**:

1. Check allocated ports:

   ```bash theme={null}
   ssh root@SERVER_IP
   cat /opt/preview-deployer/deployments.json | jq '.portAllocations'
   ```

2. Find process using port:

   ```bash theme={null}
   lsof -i :{PORT}
   ```

3. Cleanup old deployment (use the full deployment id from `GET /api/previews`, e.g. `my-org-my-app-12`):
   ```bash theme={null}
   curl -X DELETE http://SERVER_IP:3000/api/previews/{deploymentId}
   ```
   See [Orchestrator API](/reference/orchestrator-api) for full endpoint details.

### Nginx Configuration Errors

**Symptoms**: Preview URL returns 502 Bad Gateway

**Solutions**:

1. Check nginx config syntax:

   ```bash theme={null}
   ssh root@SERVER_IP
   nginx -t
   ```

2. Verify preview config exists:

   ```bash theme={null}
   cat /etc/nginx/preview-configs/{projectSlug}-pr-{PR_NUMBER}.conf
   ```

3. Check nginx error logs:

   ```bash theme={null}
   tail -f /var/log/nginx/error.log
   ```

4. Verify app container is running:

   ```bash theme={null}
   docker ps | grep {projectSlug}-pr-{PR_NUMBER}
   ```

5. Test proxy directly:
   ```bash theme={null}
   curl -H "Host: SERVER_IP" http://localhost/{projectSlug}/pr-{PR_NUMBER}/
   ```

## Runtime Issues

### Container Crashes

**Symptoms**: Preview works initially but stops responding

**Solutions**:

1. Check container status:

   ```bash theme={null}
   docker ps -a | grep {projectSlug}-pr-{PR_NUMBER}
   ```

2. View container logs:

   ```bash theme={null}
   docker logs {projectSlug}-pr-{PR_NUMBER}-app
   ```

3. Check resource usage:

   ```bash theme={null}
   docker stats {projectSlug}-pr-{PR_NUMBER}-app
   ```

4. Restart container:
   ```bash theme={null}
   cd /opt/preview-deployments/{projectSlug}/pr-{PR_NUMBER}
   docker compose restart app
   ```

### Database Connection Issues

**Symptoms**: App can't connect to database

**Solutions**:

1. Verify database container is running:

   ```bash theme={null}
   docker ps | grep {projectSlug}-pr-{PR_NUMBER}-db
   ```

2. Check database logs:

   ```bash theme={null}
   docker logs {projectSlug}-pr-{PR_NUMBER}-db
   ```

3. Test database connection:

   ```bash theme={null}
   docker exec {projectSlug}-pr-{PR_NUMBER}-db pg_isready -U preview
   ```

4. Verify connection string in app:
   ```bash theme={null}
   docker exec {projectSlug}-pr-{PR_NUMBER}-app env | grep DATABASE_URL
   ```

### Cleanup Not Working

**Symptoms**: Old previews not being cleaned up

**Solutions**:

1. Check cleanup service is running:

   ```bash theme={null}
   ssh root@SERVER_IP
   journalctl -u preview-orchestrator | grep cleanup
   ```

2. Verify TTL configuration:

   ```bash theme={null}
   cat ~/.preview-deployer/config.yml | grep cleanup_ttl_days
   ```

3. Manually trigger cleanup (use deployment id from `GET /api/previews`, e.g. `my-org-my-app-12`):

   ```bash theme={null}
   curl -X DELETE http://SERVER_IP:3000/api/previews/{deploymentId}
   ```

4. Check deployment age:
   ```bash theme={null}
   cat /opt/preview-deployer/deployments.json | jq '.deployments."{deploymentId}"'
   ```

## Performance Issues

### Slow Builds

**Solutions**:

1. Use Docker layer caching
2. Optimize Dockerfile (multi-stage builds)
3. Use smaller base images
4. Cache dependencies in separate layer

### High Resource Usage

**Solutions**:

1. Reduce max concurrent previews
2. Lower container resource limits
3. Use smaller droplet size
4. Enable cleanup of old previews

### Memory Issues

**Symptoms**: Droplet runs out of memory

**Solutions**:

1. Check memory usage:

   ```bash theme={null}
   free -h
   docker stats
   ```

2. Reduce container memory limits

3. Cleanup old previews

4. Upgrade droplet size

## Security Issues

### Webhook Signature Verification Failed

**Solutions**:

1. Verify webhook secret matches:

   ```bash theme={null}
   cat ~/.preview-deployer/config.yml | grep webhook_secret
   ```

2. Check GitHub webhook configuration

3. Verify payload is not modified

### Unauthorized Repository Access

**Solutions**:

1. Check `ALLOWED_REPOS` environment variable
2. Verify repository format: `owner/repo`
3. Check orchestrator logs for rejection messages

## Debugging Tips

### Enable Debug Logging

Set `LOG_LEVEL=debug` in the orchestrator environment (or set Ansible variable `orchestrator_log_level: debug`). Debug lines then appear in the same file as info logs: `/opt/preview-deployer/logs/orchestrator.log`. View them with:

```bash theme={null}
tail -f /opt/preview-deployer/logs/orchestrator.log
```

To set via systemd override:

```bash theme={null}
ssh root@SERVER_IP
systemctl edit preview-orchestrator
# Add: Environment="LOG_LEVEL=debug"
systemctl daemon-reload
systemctl restart preview-orchestrator
```

### Check All Services

```bash theme={null}
ssh root@SERVER_IP

# Docker
systemctl status docker
docker ps

# Nginx
systemctl status nginx
nginx -t

# Orchestrator
systemctl status preview-orchestrator
tail -n 50 /opt/preview-deployer/logs/orchestrator.log
# Or: journalctl -u preview-orchestrator -n 50
```

### Manual Testing

Test orchestrator API (see [Orchestrator API](/reference/orchestrator-api) for full endpoint reference):

```bash theme={null}
curl http://SERVER_IP:3000/health
curl http://SERVER_IP:3000/api/previews
```

Test webhook:

```bash theme={null}
# Generate signature
SECRET="your-webhook-secret"
PAYLOAD='{"action":"opened",...}'
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)

curl -X POST http://SERVER_IP:3000/webhook/github \
  -H "Content-Type: application/json" \
  -H "X-Hub-Signature-256: sha256=$SIGNATURE" \
  -d "$PAYLOAD"
```

## Getting Help

If you're still stuck:

1. Check logs for error messages
2. Review [Architecture Documentation](/architecture)
3. Check [Configuration Reference](/configuration)
4. Open an issue on GitHub with:
   * Error messages
   * Logs (sanitized)
   * Steps to reproduce
   * System information

## Common Error Messages

### "Repository not in allowed list"

* Add repository to `ALLOWED_REPOS` environment variable
* Restart orchestrator service

### "Port allocation out of range"

* PR number too large (>56,000)
* Use smaller PR numbers or upgrade port allocation strategy

### "Health check timeout"

* Verify health check endpoint exists
* Check health check path in config
* Increase timeout in docker-manager.ts

### "Docker build failed"

* Check Dockerfile syntax
* Verify all dependencies are available
* Check build logs for specific errors

### "Nginx reload failed"

* Check nginx config syntax: `nginx -t`
* Verify preview config file format
* Check nginx error logs
