Troubleshooting
Find the stage that fails, then match the exact error to its fix.
Find the stage that fails (setup, start, host install, host ready, preview or sign-in), then match the exact message in its table.
Collect logs
# on the control plane, in platinum/infra/compose
docker compose ps
docker compose logs migrate
docker compose logs -f server
# on a sandbox host
sudo cat /var/log/platinum-install.log
sudo journalctl -u platinum-host-agent -u platinum-edge-proxy -fFix setup and start
| Message | Fix |
|---|---|
--version is required | Pass --version X.Y.Z, or edge. |
--domain: api.example.com is the placeholder | Use your own hostname. |
could not detect this machine's address; pass --private-ip | Pass the address your hosts reach this machine on. |
run setup.sh (it sets PLATINUM_VERSION) | Run setup.sh before docker compose. |
refusing to start: ADMIN_TOKEN is the dev default but PT_PRODUCTION=1 | Set a real ADMIN_TOKEN in .env. The same rule covers EDGE_HMAC_SECRET. |
migrate exits non-zero | Read docker compose logs migrate, fix the cause, then docker compose up -d. The server does not start until migrate succeeds. |
| Database authentication fails | POSTGRES_PASSWORD changed after the database was created, often by setup.sh --force. Restore the old value from your .env backup. |
Caddy cannot bind :80 or :443 | Another process holds the port: sudo ss -ltnp 'sport = :80'. |
/health checks the process and the database. /health/deep also checks that the database accepts writes.
Fix a host install
| Message | Fix |
|---|---|
/dev/kvm not present | Turn on VT-x or AMD-V in firmware. See Hardware. |
needs apt (Ubuntu/Debian) | Install on Ubuntu 24.04. |
[install] no region | Mint the token with a region, or pass it after the API URL. |
curl: (22) … 403 on /install.sh (body: forbidden: valid host bootstrap token required) | The token is wrong, expired or already used. Mint a new one. |
FATAL: edge-proxy is not active and listening on :80 | Another service holds :80, or the unit crashed. Read journalctl -u platinum-edge-proxy, free the port, and re-run the command. |
Fix a host that never becomes ready
A new host stays in verifying until its self-test passes. The test runs when the agent starts.
sudo journalctl -u platinum-host-agent -b | grep self-test
# [host-agent] self-test FAILED: <reason> — staying in 'verifying' state; …Fix the reason it names, then sudo systemctl restart platinum-host-agent.
| Symptom | Fix |
|---|---|
| The host never appears | From the host, curl -sv https://api.example.com/health. |
hb_age_s keeps growing | The host cannot reach the API. Check CONTROL_PLANE_URL in /etc/platinum/host.env. |
ready, but no sandbox is ever placed | The control plane cannot reach :18048. Check that PT_PRIVATE_IP (or PT_CP_ADVERTISE_IP) is the address the control plane dials hosts from, then reinstall the host. |
s3: DEGRADED or s3: disabled | See Object storage. |
A sandbox stuck in provisioning usually means no host is ready. Search the host log for the sandbox id for anything else.
Fix preview URLs
Platinum's error page names a short reason. Any other page came from the app inside the sandbox.
| Reason | Fix |
|---|---|
host-format | The hostname is not <port>-<sandbox>.<PT_SBX_DOMAIN>. Check PT_SBX_DOMAIN and DNS. |
no-such-sandbox | The sandbox id is wrong, or it was deleted. If every preview fails, check DATABASE_URL in the host's /etc/platinum/edge-proxy.env. |
sandbox-not-placed-on-a-host-yet | Wait until the sandbox is running. |
port-not-exposed | Expose the port first. |
token-required | The port is private. Use the full URL with its token. |
bad-token | Expose again for a fresh URL. If every token fails, EDGE_HMAC_SECRET differs between the control plane and the host. |
peer-not-trusted | The request reached a host's :80 from an address not in EDGE_TRUSTED_PEERS. |
| TLS or DNS error | dig +short 8080-x.sbx.example.com must return the control plane. See Domains & TLS. |
An app's own 404 usually means it listens on 127.0.0.1. Bind it to 0.0.0.0.
Fix sign-in and email
| Symptom | Fix |
|---|---|
| No email arrives | With no provider, the log shows [email] no provider configured and nothing is sent. Set RESEND_API_KEY or MAILTRAP_API_TOKEN. |
| Sign-up refused | PT_SIGNUP_MODE is invite-only or closed. Use an address in PT_ADMIN_EMAILS, or invite it. |
| Signed in, but not a platform admin | The address is not verified yet. See Console. |