Troubleshooting
A practical guide to diagnosing and fixing common BRIDGEPORT issues, with a quick-reference table and step-by-step debugging instructions.
General Debugging
Section titled “General Debugging”Reading BRIDGEPORT Logs
Section titled “Reading BRIDGEPORT Logs”BRIDGEPORT logs structured JSON in production and pretty-printed output in development. Start here for any issue:
# View recent logsdocker logs bridgeport --tail 100
# Follow logs in real timedocker logs bridgeport -f
# Search for errorsdocker logs bridgeport 2>&1 | grep -i errorHealth Endpoint
Section titled “Health Endpoint”The /health endpoint gives you a quick status check:
curl -s http://localhost:3000/health | jq .{ "status": "ok", "timestamp": "2026-02-25T12:00:00.000Z", "version": "1.0.0", "bundledAgentVersion": "20260220-abc1234", "cliVersion": "20260218-def5678"}If this endpoint does not respond, BRIDGEPORT is not running or not reachable.
Common Log Messages
Section titled “Common Log Messages”| Log Message | Meaning |
|---|---|
=== BRIDGEPORT Startup === | Entrypoint script began |
Applying migrations... | Prisma is running pending database migrations |
Prisma Migrate applied all migrations. | Migrations completed successfully |
=== Starting BRIDGEPORT === | Application is about to start |
BRIDGEPORT running at http://0.0.0.0:3000 | Startup completed, ready to accept requests |
[Scheduler] Starting with intervals: | Background scheduler started |
[Scheduler] Health check failed for server X | SSH or URL health check failed for a server |
[Scheduler] Auto-deploying container image | Auto-update triggered a deployment |
Transient database contention; returning 503 | A write hit SQLite write-lock contention that outlasted the retry budget; the request got a retryable 503. Rare — see “Transient 503s under load” below. |
Crypto not initialized | MASTER_KEY is missing or invalid |
Querying a Live Instance (Read-Only API Access)
Section titled “Querying a Live Instance (Read-Only API Access)”When you (or a coding agent like Claude Code) are debugging an issue, it’s often faster to read the actual state of a running instance than to reason from the code alone — “which services exist? what tag is deployed? is this server marked unhealthy?”. BRIDGEPORT’s API answers all of these, and a read-only service account token lets you query it safely without touching anything.
1. Create a read-only token
In the UI: Admin → Service Accounts → New, give it the viewer role, then
mint a token. A viewer token is read-only — every mutating call is rejected.
2. Put the URL + token in your .env (see .env.example):
BRIDGEPORT_URL="https://deploy.example.com"BRIDGEPORT_TOKEN="bport_pat_..."These two variables are not read by the BRIDGEPORT server — they’re purely
for local tooling. .env is gitignored, so the token never gets committed.
Treat it like any secret and revoke it from the Service Accounts page when done.
3. Query the API (everything authenticates with Authorization: Bearer):
# Load the vars (from the repo root)set -a; . ./.env; set +a
# Who am I / what can this token do?curl -s -H "Authorization: Bearer $BRIDGEPORT_TOKEN" "$BRIDGEPORT_URL/api/auth/me" | jq '{role, scopes}'
# List environments, then services in one of themcurl -s -H "Authorization: Bearer $BRIDGEPORT_TOKEN" "$BRIDGEPORT_URL/api/environments" | jq '.environments[] | {id, name}'curl -s -H "Authorization: Bearer $BRIDGEPORT_TOKEN" "$BRIDGEPORT_URL/api/environments/<envId>/services" | jq '.services[] | {name, imageTag, healthStatus, serviceTypeId}'The full surface is documented in the API Reference and the
live OpenAPI spec at GET /openapi.json (Swagger UI at /api/docs). A viewer
token is rejected (403, code: FORBIDDEN_ROLE) on any mutating call, so it’s
safe to hand to automated tooling.
A token is a bearer credential — anyone holding it has its scopes. Never paste it into a file that gets committed, a chat log, or a shared terminal recording. Prefer short-lived tokens and rotate them after a debugging session.
Quick Troubleshooting Table
Section titled “Quick Troubleshooting Table”| Symptom | Likely Cause | Solution |
|---|---|---|
| Container exits on startup | Missing MASTER_KEY or JWT_SECRET | Check .env has all required variables |
| Container exits with migration error | Bad migration SQL in new release | Restore backup, pin previous version, report bug |
| Can’t log in (no users) | ADMIN_EMAIL/ADMIN_PASSWORD not set on first boot | Set env vars, delete database, restart |
| Can’t connect to server | SSH key issue or firewall | Check key in Settings > SSH, test from Monitoring > Agents |
| Container not found during discovery | Service not running or name changed | Check docker ps on the server, run manual discovery |
| Health check always fails | Wrong health endpoint URL | Verify the URL in service settings, test with curl |
| Agent not reporting metrics | Token mismatch or network issue | Regenerate token, verify BRIDGEPORT_SERVER URL |
| Notifications not being sent | SMTP/Slack not configured | Check Admin > Notifications for channel configuration |
| Deploy fails with “image not found” | Registry credentials expired or wrong | Re-enter credentials in Registries page |
| Backup fails with timeout | Large database exceeds default timeout | Increase pgDumpTimeoutMs in System Settings |
| UI shows old version | Browser cache | Hard refresh (Ctrl+Shift+R or Cmd+Shift+R) |
| Metrics page is slow | Large metrics history | Reduce retention in environment monitoring settings |
MCP client gets 404 on /mcp | MCP server disabled | Set MCP_ENABLED=true and restart the container |
| MCP client sees no/few tools | Token role or env scope too narrow | Use an operator/all-environments token; call get_capabilities |
Occasional 503 SERVICE_UNAVAILABLE under heavy load | SQLite write-lock contention outlasted the retry budget | Retry the request (the response sets Retry-After); see below |
Transient 503s under load
Section titled “Transient 503s under load”BRIDGEPORT serves every request through a single SQLite connection, so under
normal load DB work is naturally serialized and never self-contends. Contention
can still arise when another writer holds the SQLite write lock — a
long-running external transaction, a WAL checkpoint, or a second process
touching the database file (for example a test harness that resets state between
runs). Two cases result: a SQLITE_BUSY (the lock is held past busy_timeout)
or a SQLITE_BUSY_SNAPSHOT (a stale read snapshot tried to upgrade to a write —
busy_timeout can’t help with this one).
Both are transient and retryable. BRIDGEPORT retries the operation
automatically with jittered backoff (DB_RETRY_* settings); if the contention
outlasts the retry budget the request returns 503 with code: SERVICE_UNAVAILABLE and a Retry-After header — never an opaque 500. A
well-behaved client (including the Terraform provider) should retry. Persistent
503s point at a genuine second writer on the DB file — remove it, or raise
DB_RETRY_MAX_ATTEMPTS / SQLITE_BUSY_TIMEOUT_MS.
Container Won’t Start
Section titled “Container Won’t Start”Missing Environment Variables
Section titled “Missing Environment Variables”BRIDGEPORT requires three environment variables to start. If any are missing, it exits immediately:
# Check your .env file has theseDATABASE_URL=file:/data/bridgeport.dbMASTER_KEY=<your-32-byte-base64-key>JWT_SECRET=<your-32-byte-base64-key>Generate new keys if needed:
openssl rand -base64 32 # For MASTER_KEYopenssl rand -base64 32 # For JWT_SECRET (use a different value)Database File Permissions
Section titled “Database File Permissions”If the data directory is not writable, BRIDGEPORT cannot create or modify the database:
# Check ownership (should be writable by UID 1000, the node user)ls -la ./data/
# Fix permissions if neededsudo chown -R 1000:1000 ./data/Migration Errors
Section titled “Migration Errors”If the logs show a Prisma migration error during startup:
- Check the exact error in
docker logs bridgeport - This usually indicates a bug in a new release’s migration
- Restore your pre-upgrade backup and pin the previous version
- See Database Migration Issues for details
Authentication Issues
Section titled “Authentication Issues”No Admin User on First Boot
Section titled “No Admin User on First Boot”The initial admin user is only created when:
ADMIN_EMAILandADMIN_PASSWORDare set in the environment- No users exist in the database yet
If you started BRIDGEPORT without these variables, the database was created with no users.
Fix: Stop BRIDGEPORT, delete the database, set the variables, and restart:
docker compose stoprm ./data/bridgeport.db# Make sure ADMIN_EMAIL and ADMIN_PASSWORD are in .envdocker compose up -dForgot Admin Password
Section titled “Forgot Admin Password”If an admin account exists but you forgot the password:
- Another admin can reset it from the Admin > Users page
- If no other admin exists, you will need to reset the database or update the password hash directly in the SQLite database
JWT Token Expired
Section titled “JWT Token Expired”JWT tokens expire after 7 days. The UI handles token refresh automatically. If using API tokens for scripts, create a long-lived API token from the My Account modal instead.
SSH Connection Failures
Section titled “SSH Connection Failures”Diagnosis Steps
Section titled “Diagnosis Steps”-
Verify the SSH key is uploaded in Settings > SSH for the correct environment
-
Check the SSH user in Settings > General matches the authorized user on the server
-
Test connectivity from Monitoring > Agents using the SSH test feature
-
Try manual SSH from the BRIDGEPORT container:
Terminal window docker exec -it bridgeport shssh -i /tmp/test-key user@server-ip -o StrictHostKeyChecking=no
Common Causes
Section titled “Common Causes”| Issue | Fix |
|---|---|
| ”Connection refused” | Ensure sshd is running on port 22 and firewall allows connections from BRIDGEPORT’s network |
| ”Permission denied” | Verify the public key is in ~/.ssh/authorized_keys on the target server |
| ”Host key verification failed” | BRIDGEPORT uses StrictHostKeyChecking=no by default; this error is rare but check SSH config |
| ”Key format not supported” | BRIDGEPORT expects OpenSSH format keys. Convert with ssh-keygen -p -m PEM -f key.pem |
| ”Timeout” | Network routing issue. Verify the server hostname/IP is reachable from the Docker network |
Docker Socket Issues
Section titled “Docker Socket Issues”If using socket mode for managing containers on the host:
Socket Not Mounted
Section titled “Socket Not Mounted”Verify the Docker socket is mounted in docker-compose.yml:
volumes: - /var/run/docker.sock:/var/run/docker.sockPermission Denied on Socket
Section titled “Permission Denied on Socket”Find the Docker socket group ID and add it to the container:
stat -c '%g' /var/run/docker.sock# Output: 999 (or similar)Add to your compose file:
services: bridgeport: group_add: - "999" # Use the actual group ID from statAgent Not Reporting
Section titled “Agent Not Reporting”Check Agent Status
Section titled “Check Agent Status”On the target server:
# Check if the agent service is runningsystemctl status bridgeport-agent
# View agent logsjournalctl -u bridgeport-agent -f --no-pager -n 50Verify Connectivity
Section titled “Verify Connectivity”From the agent server, check that BRIDGEPORT is reachable:
curl http://your-bridgeport-host:3000/healthIf using an internal IP, ensure agentCallbackUrl is set correctly in Admin > System Settings.
Token Mismatch
Section titled “Token Mismatch”If the agent logs show authentication errors:
- Go to the server’s detail page in BRIDGEPORT
- Regenerate the agent token
- Redeploy the agent (this updates the token automatically)
Docker Access
Section titled “Docker Access”The agent needs access to the Docker socket to collect container metrics:
ls -la /var/run/docker.sock# Add the agent user to the docker group if needed:sudo usermod -aG docker $(whoami)Deployment Failures
Section titled “Deployment Failures”Image Not Found
Section titled “Image Not Found”If a deploy fails with “image not found” or “pull access denied”:
- Verify the image name and tag exist in your registry
- Check that registry credentials are valid in the Registries page
- Test manually from the target server:
docker pull your-image:tag
Health Check Fails After Deploy
Section titled “Health Check Fails After Deploy”If deployment orchestration fails at the health check step:
- Check the deployment plan detail page for the specific error
- Verify the service’s
healthCheckUrlreturns a 2xx status - Increase
healthWaitMsif the service takes time to start - Increase
healthRetriesfor services with slow startup
Rollback Was Triggered
Section titled “Rollback Was Triggered”If auto-rollback activated during an orchestrated deployment:
- Check the deployment plan detail page — it shows which step failed
- The
errorandlogsfields on the failed step contain the root cause - All previously deployed services were automatically rolled back to their previous tags
Backup Failures
Section titled “Backup Failures”PostgreSQL Backup Fails
Section titled “PostgreSQL Backup Fails”| Symptom | Fix |
|---|---|
| ”Connection refused” | Verify database host/port are reachable from BRIDGEPORT’s server |
| ”Authentication failed” | Re-enter database credentials on the database detail page |
| ”pg_dump: command not found” | The BRIDGEPORT Docker image includes postgresql16-client. If using a different version, ensure compatibility |
| Timeout | Increase pgDumpTimeoutMs in Admin > System Settings (default: 300000ms / 5 minutes) |
Spaces Upload Fails
Section titled “Spaces Upload Fails”- Verify storage credentials in Admin > Storage
- Ensure the target bucket exists
- Check that the access key has write permissions to the bucket
Scheduled Backups Not Running
Section titled “Scheduled Backups Not Running”- Confirm the scheduler is enabled:
SCHEDULER_ENABLED=true(default) - Check the backup schedule is enabled on the database detail page
- Verify
nextRunAtis set — if it showsnull, the schedule may need to be re-saved
Notification Delivery Issues
Section titled “Notification Delivery Issues”In-App Notifications Not Appearing
Section titled “In-App Notifications Not Appearing”- Check that the notification type is enabled in Admin > Notifications
- Verify the user’s notification preferences include
in_appfor that type - Check the notification bell icon — you may need to refresh
Email Notifications Not Sending
Section titled “Email Notifications Not Sending”- Verify SMTP is configured in Admin > Notifications > SMTP
- Test the SMTP connection from the admin page
- Check BRIDGEPORT logs for SMTP errors:
docker logs bridgeport 2>&1 | grep -i smtp - Verify the user has
emailenabled in their notification preferences
Slack Notifications Not Sending
Section titled “Slack Notifications Not Sending”- Verify Slack channels are configured in Admin > Notifications > Slack
- Check that notification types are routed to the correct Slack channel
- Test the webhook URL from the admin page
Performance Issues
Section titled “Performance Issues”High CPU or Memory Usage
Section titled “High CPU or Memory Usage”- Reduce metrics collection frequency: Raise the
SCHEDULER_*interval env vars (e.g., changeSCHEDULER_METRICS_INTERVALfrom 60s to 300s — see Configuration Reference → Scheduler) - Reduce retention: Lower
METRICS_RETENTION_DAYS(env var) to reduce database size - Check database size:
Terminal window ls -lh ./data/bridgeport.db - Vacuum the database (requires stopping BRIDGEPORT):
Terminal window docker compose stopsqlite3 ./data/bridgeport.db "VACUUM;"docker compose start
Slow Page Loads
Section titled “Slow Page Loads”- Monitoring pages: Reduce the selected time range or the number of monitored resources
- Health check logs: Reduce
healthLogRetentionDaysin Admin > System Settings > Retention - Audit logs: Reduce
auditLogRetentionDaysin System Settings
Database Migration Issues
Section titled “Database Migration Issues”BRIDGEPORT runs prisma migrate deploy automatically on every startup. If a migration fails:
- Check the error message in
docker logs bridgeport - Do not modify the database manually — this breaks Prisma’s migration state
- Restore your pre-upgrade backup if the migration corrupted data
- Pin the previous version until the issue is fixed upstream
For legacy databases (created before migration tracking was added), BRIDGEPORT automatically creates a migration baseline on first startup. This is a one-time operation and should not require intervention.
MCP Server Issues
Section titled “MCP Server Issues”The MCP server is opt-in and off by default. Common issues when connecting an AI agent:
/mcp returns 404
Section titled “/mcp returns 404”The route is only registered when MCP is enabled. Verify:
MCP_ENABLEDis set totrueor1— it is strict-parsed, sofalse,0, an empty string, or any other value keeps it disabled.- The container was restarted after setting it (it’s a deployment-level env var, not a runtime toggle).
- Check the boot logs:
docker logs bridgeport 2>&1 | grep -i mcp.
You can confirm status without a client at Admin > MCP Server (/admin/mcp), which shows the live enabled/disabled badge and the endpoint URL.
Client connects but sees no tools (or fewer than expected)
Section titled “Client connects but sees no tools (or fewer than expected)”The tools advertised to a session are derived from the token’s role and environment scope:
- A viewer token sees read tools only. Write tools (
deploy_service,restart_deployment, …) require an operator/admin token (services:write). - An environment-scoped token sees only the tools backed by environment routes — every global-route tool (all write tools, plus global reads like
get_server) is hidden because it would always returnFORBIDDEN_SCOPE. For the full surface, use an all-environments token. - Call the
get_capabilitiestool to see the exact scopes and tool list your token resolved to.
Client can’t reach /mcp through a reverse proxy
Section titled “Client can’t reach /mcp through a reverse proxy”If the transport rejects the request, check MCP_ALLOWED_HOSTS: when set, the request Host header must match one of the listed public hostnames (DNS-rebinding protection). It is distinct from HOST (the socket bind address). Ensure TLS terminates at the proxy and the bearer token travels only over HTTPS.
See the MCP Server Reference for client setup and the full tool/scope reference.
Lost MASTER_KEY
Section titled “Lost MASTER_KEY”If you lose your MASTER_KEY, all encrypted data becomes irrecoverable:
- All secrets
- SSH keys for every environment
- Registry credentials
- SMTP passwords
- Slack webhook URLs
- Spaces secret keys
What still works: Servers, services, environments, config files, users, metrics, audit logs, deployment history, and all other unencrypted data.
Recovery steps:
- Generate a new key:
openssl rand -base64 32 - Update
.envwith the newMASTER_KEY - Restart BRIDGEPORT
- Re-create all encrypted resources (SSH keys, secrets, registry credentials, SMTP config)
See Backup & Restore > Lost MASTER_KEY for detailed steps.
Related Documentation
Section titled “Related Documentation”- Backup & Restore — recovery procedures
- Security & Hardening — securing your deployment
- Upgrades — upgrade-specific issues
- Configuration Reference — environment variable reference