Troubleshooting
A pragmatic fix-guide for the most common problems. For each symptom: brief explanation → diagnostics → fix.
General: reading logs
journalctl -u dvb-warppool -f --since "5 min ago"
For Docker:
docker logs -f dvb-warppool --since 5m
Temporarily raise the log level:
RUST_LOG=warppool=debug,info dvb-warppool-daemon
Targeted per crate:
RUST_LOG=warppool_stratum_v1=trace,warppool_bitcoin_rpc=debug,info dvb-warppool-daemon
RPC
getblockchaininfo failed: HTTP 401 — credentials rejected
Cookie or user/pass mismatch.
Diagnosis:
# Cookie auth:
cat ~/.bitcoin/.cookie # should be "user:hexhash"
# user/pass auth:
grep -E "^rpc(user|password)" ~/.bitcoin/bitcoin.conf
Fix:
- Cookie mode: make sure
node.rpc_cookie_pathinconfig.tomlpoints to the correct file. Bitcoin Core has its own cookie files for regtest/testnet (~/.bitcoin/regtest/.cookie,~/.bitcoin/testnet3/.cookie). The setup wizard typically shows the right path. - user/pass mode: in
secrets.toml,rpc_user+rpc_passmust match the values inbitcoin.conf. Insecrets.toml, notconfig.toml— otherwise the daemon complains at startup. - On permission errors: bitcoind runs as a different user; the cookie is
0600and unreadable for your warppool user. The setup wizard catches this and suggestschmod g+r+ group-add.
getblocktemplate failed: -8 ...
Bitcoin Core is reachable, but says no to the template.
Possible causes:
- IBD running:
warppool_rpc_ibd == 1. Wait until sync completes. - Wallet locked:
getblocktemplatewithout-walletbroadcast=0needs an unlocked wallet in Core. Unusual in a pool context, though — we use GBT without a wallet. - Too few peers:
getpeerinfoshows 0 or 1. Core then refuses to mine to avoid ending up on a minority fork. Fix: wait, or use-minimumchainwork=0for tests.
RPC latency high (Prometheus shows p99 > 1s)
Diagnosis:
- Are many RPCs running in parallel? The daemon normally does ~1-5/s in steady state. If p99 is high: is Bitcoin Core on a slow disk or swapping?
tx-index=1setup on HDD: makes GBT slow. SSD recommended.- Pruned node + old block request: doesn't happen on the normal pool path, but backup/restore workflows can trigger it.
Fix: usually a disk bottleneck. iotop / iostat shows this quickly.
ZMQ
Daemon only uses poll-loop, no ZMQ
Log line at startup:
zmq watcher: WARPPOOL_ZMQ_HASHBLOCK_ADDR not set, falling back to poll-only
Fix: set in config.toml:
[node]
zmq_hashblock_addr = "tcp://127.0.0.1:28332"
And in bitcoin.conf:
zmqpubhashblock=tcp://127.0.0.1:28332
Bitcoin Core must be restarted after this change.
ZMQ connection refused / timeout
Bitcoin Core isn't listening on the ZMQ port. Diagnosis:
ss -tlnp | grep 28332
# Expected output: bitcoind listens on 0.0.0.0:28332 or 127.0.0.1:28332
If nothing: the bitcoin.conf line is missing or Bitcoin Core wasn't
restarted.
If 0.0.0.0: ZMQ is exposed — often necessary with a Docker bridge (daemon
and bitcoind in different containers). On a direct host
tcp://127.0.0.1:28332 should be enough.
Stratum / miner connections
Workers reconnect-loop every few seconds
Symptom: many session ended with shares_accepted = 0 in the logs. Many
miner-disconnect events in the notifier (or, with Phase 15 debounce, one every 30s).
Common causes:
- Wrong worker address: a V1 miner submits an address the ShareValidator
doesn't accept. Logs show
mining.authorizewith a bad address. - VarDiff too aggressive: the initial diff was too high, the miner can't
produce shares within the
target_seconds_per_sharewindow, retargets down quickly, and some firmwares don't like rapid retargets. Fix: a highermin_diffor a lowerinitial_diffin[vardiff]. - Auth rate limit kicks in: at >
auths_per_secauth attempts per IP you get rejected. In the log:auth rate-limited. For legitimate cases with multiple workers behind NAT: raise the rate limit.
Miner can't connect at all
# Is the pool port reachable?
nc -v pool.local 3333
# TLS port?
openssl s_client -connect pool.local:3334 -showcerts
If local is OK but external isn't: firewall / NAT. The UPnP wizard in setup (Phase 11) can open this automatically, but only if the FritzBox / router allows UPnP. Some ISP routers have UPnP off by default.
Notifier doesn't fire
notifier sink skipped: env var foo not set
At daemon start, the env vars for the sink aren't present. With systemd:
[Service]
EnvironmentFile=/etc/default/dvb-warppool
With /etc/default/dvb-warppool as a chmod-600 file:
TELEGRAM_BOT_TOKEN=123:abc...
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
POOL_SMTP_PASSWORD=...
For Docker: via -e KEY=val or an env-file in docker-compose.yml.
Test button shows err
Click Test in the admin UI → err badge. The specific error shows as a
tooltip on the badge (hover). Common cases:
- Telegram:
bot not found— wrong bot_token.chat not found— wrong chat_id or the bot was removed from the chat. - Discord:
Unknown Webhook— webhook was deleted. - Slack:
invalid_payload— very rare; usually a typo in the webhook URL. - Email:
Could not resolve host— wrong SMTP host.authentication failed— wrong password env.unable to connect: connection refused— wrong port or firewall.
Spam from miner-disconnect events
Per-worker debounce is 30s (WARPPOOL_DISCONNECT_DEBOUNCE_SECS). If that's
too noisy: set the env var to 300 (5min).
If a single worker keeps disconnecting: that's a real problem on the miner
side — check the logs on the miner hardware (the Bitaxe web interface has
Logs; Antminer has SSH access).
Auto-update
Update fails: download/verify: sha256 mismatch
The asset on GitHub was changed between when you saw the release and
downloaded it (rare), or you passed the wrong sha256. For POST /api/admin/update,
always take the sha256 from the release notes file or from the GitHub
API itself — never type it manually.
Update applied but daemon keeps restarting (StartLimitBurst)
The Phase 8f rollback hook fired. The systemd journal shows:
OnFailure=dvb-warppool-rollback.service triggered
rollback.sh copies the .backup back and runs systemctl restart. If the
backup is also broken: install the old version manually or roll back from
a snapshot.
cosign verify-blob failed
When cosign_verify=true is set in the update request: the signature doesn't
match the asset. Possible causes:
- The asset is authentic but the signature file is stale
- The asset has been tampered with
The default is cosign_verify=false — only use cosign if you've explicitly
configured the trust anchor (public key or Sigstore root).
Setup wizard
"Cookie not readable"
Most likely a permission issue. The setup wizard shows the exact path + suggested fix:
sudo usermod -a -G bitcoin warppool # one-time
sudo chmod g+r ~/.bitcoin/.cookie # after every Core restart
Cleaner: configure bitcoind with rpcauth=warppool:saltedhash and use
user/pass mode instead of the cookie.
UPnP test "no gateway found"
The router has UPnP off, or the daemon is bound to the wrong interface. Some ISP routers (Vodafone, some FritzBoxes with a locked-down user account) don't allow UPnP from the outside.
Fix:
- Enable UPnP in the router web interface
- Alternatively: set port forwarding manually (3333/3334)
bitcoin.conf snippet suggests recommendations for keys that are already set
If the setup wizard says "add zmqpubhashblock=..." even though it's already
there — usually the wrong conf path. Check bitcoin-cli -datadir=… getrpcinfo
to see the datadir that's actually in use.
API / UI
/api/admin/* returns 401
Admin auth is configured but the token is missing from the request:
curl -H "Authorization: Bearer wpat_…" http://pool.local:18334/api/admin/notifier/sinks
Generate a token with dvb-warppool-cli token-create -n my-script — the raw
token is shown only once.
/api/admin/* returns 503 "auth disabled"
secrets.toml has no admin_password_hash or jwt_secret. Fix:
dvb-warppool-cli hash-password
and paste the output into secrets.toml.
UI doesn't load — Failed to fetch /api/...
Direct --ui-dir mode or dev mode? In dev (pnpm dev), Vite runs with a
proxy /api → http://127.0.0.1:18334. In production: the UI is served
directly by the daemon via --ui-dir. Check the daemon startup log:
serving static UI from daemon ui_dir=/usr/share/dvb-warppool/ui
If not present: the --ui-dir flag is missing or the directory doesn't exist.
Vendor probes (Phase 22)
Miner is discovered via mDNS but no telemetry
Possible causes:
| Vendor | mDNS discovery | Telemetry probe |
|---|---|---|
| Bitaxe | ✅ _bitaxe._tcp.local. | ✅ AxeOS HTTP /api/system/info |
| NerdNOS / NerdOctaxe | ✅ _nerdminer._tcp.local. | ✅ AxeOS-compatible |
| Antminer S19/S21/S23 | ❌ no mDNS | ✅ CGMiner socket 4028 — add manually in /admin/miners with vendor=antminer |
| Whatsminer M30S/M50 | ❌ | ✅ CGMiner socket — vendor=whatsminer |
| Avalon A12xx/A13xx standalone | ❌ | ✅ CGMiner socket — vendor=avalon |
| Avalon Q (home miner) | ❌ | ✅ CGMiner socket but its own field names — vendor=avalonq |
| Avalon A15xx (e.g. A1566) | ❌ | 🟡 try vendor=avalon — if the field naming differs, please file an issue with cargo run -- probe --vendor avalon --host … output |
| Braiins OS / OS+ | 🟡 via HTTP fallback when the hostname contains braiins* / bos-* | ✅ CGMiner socket 4028 with Braiins-specific field names (power_consumption_w, voltage, temp1..N) — vendor=braiins |
vendor=avalon and vendor=avalonq are separate adapters — one matches
MTavg/MTmax/GHS av, the other THSspd/TMax/Cur_Load. If you add
a Q with vendor=avalon, lots of None values come back.
Manual add command
curl -X POST -H "Authorization: Bearer wpat_..." \
-H "Content-Type: application/json" \
-d '{"host":"192.168.1.42:4028","vendor":"avalonq","label":"avalonq-1"}' \
http://pool.local:18334/api/admin/miners
Port 4028 is the CGMiner default. Some vendors reconfigure it — in that case, pass the correct port number.
Last resort
Daemon panicked and won't come up
Look at the logs. Common cases:
- DB migration failed:
sqlx::migratethrows on an inconsistent schema - Config file broken: TOML parse error with line number
- Port taken: another pool / service on 3333
Rebuild storage DB from scratch
systemctl stop dvb-warppool
mv /var/lib/dvb-warppool/pool.db /var/lib/dvb-warppool/pool.db.broken
systemctl start dvb-warppool # daemon creates a fresh DB and runs migrations
You will lose:
- VarDiff snapshots per worker (every miner starts at initial_diff)
- Aggregated hashrate history (raw shares > 1h are evicted anyway)
- Audit log
Blocks-found is NOT the source of truth in the DB — those live in the
Bitcoin blockchain itself. The block list is lazily re-populated on the
first request via getblock RPCs.
See also
- Setup health checks — preventive diagnostics during setup
- Auto-update — update path + rollback
- Configuration Reference