Troubleshooting
Start every investigation with two commands:
curl -s https://YOUR-DOMAIN/api/healthdocker compose -f App/docker/docker-compose.yml logs syncbins --tail=200{"ok":true,"version":"…"} means the process is up. Everything else narrows from there.
Server won’t start
Section titled “Server won’t start”| Log / symptom | Cause | Fix |
|---|---|---|
BLOB_URL_SECRET is required | Missing env in production compose | Set in docker/.env: openssl rand -hex 32 |
Invalid server configuration | Zod validation failed on env | Match Configuration reference |
EADDRINUSE :8080 | Port conflict | Stop other service or change LISTEN_PORT |
| SQLite permission error | Bind mount not writable | chown/chmod on ./data for container user |
TLS / certificate issues
Section titled “TLS / certificate issues”| Symptom | Fix |
|---|---|
| Browser stuck on HTTP or cert warning | Confirm DNS A/AAAA record, ports 80+443 open, hit HTTPS not :8080 |
| Caddy loop / no cert (multi-tenant) | Ensure tenant exists — curl "https://apex/api/tls-check?domain=slug.domain" returns 200 |
| LE rate limit | Reduce repeated failed issuances; fix tls-check before retrying |
See TLS & domains.
Can’t complete onboarding / bootstrap
Section titled “Can’t complete onboarding / bootstrap”| Symptom | Fix |
|---|---|
| ”Already has devices” on fresh self-host | Someone else claimed first — use pair path, or POST /api/devices/bootstrap/restart if single-tenant orphan (see First-time setup) |
| Server unreachable from browser | Check Caddy → syncbins network, DOMAIN matches URL |
| Recovery phrase mismatch | Wrong vault — compare fingerprint in onboarding with Settings → Encryption |
Pairing failures
Section titled “Pairing failures”| Error | Fix |
|---|---|
pair_expired | Code older than 5 minutes — generate new code |
pair_invalid | Typo in six words — copy hyphenated code from Copy code button |
| Hangs on “waiting” | Keep generating device online with active session |
Client-side: Pairing more devices.
Sync / WebSocket
Section titled “Sync / WebSocket”| Symptom | Fix |
|---|---|
| Items save but don’t appear elsewhere | Check WS in browser devtools — should stay connected to wss://…/ws?token=… |
| Constant reconnect loop | Token expired (30-day session) — re-pair device |
| Stale feed after offline | Normal — client sends hello with last version on reconnect; wait for caught_up |
Protocol details: How sync works, WebSocket protocol.
Blob upload / download 403
Section titled “Blob upload / download 403”| Symptom | Fix |
|---|---|
| Upload URL rejected | storage_full — raise STORAGE_CAP_BYTES or free space (multi-tenant quotas) |
| Download 403 on local storage | BLOB_URL_SECRET changed since upload — secrets must stay stable or URLs invalidate |
| R2/Azure errors | Verify credentials in .env, bucket exists, clock skew minimal |
Wrong data / empty after upgrade
Section titled “Wrong data / empty after upgrade”- Confirm bind mount still points at
./data:/datain compose. - Check
SQLITE_PATHandLOCAL_BLOB_DIRinside container env. - If you restored backup, ensure blob files match
blob_refentries in SQLite.
Still stuck?
Section titled “Still stuck?”Hosted: info@syncbins.com (never send recovery phrase or PIN).
Self-hosted: open a GitHub issue with redacted logs, TENANT_MODE, storage backend, and steps to reproduce. On a Raspberry Pi, include docker compose exec syncbins uname -m (expect aarch64) — see Raspberry Pi.
Going deeper
Section titled “Going deeper” Configuration reference Every env var.
Error codes API failure catalogue.
Recovery scenarios User-side lockouts.