PiAxe – Pool Authorization Password Rejected
Warning — Should be addressed soon
Symptoms
- `journalctl -u piaxe` shows `mining.authorize` followed within 1 second by `result: false`, `Authorization failed`, `bad-user-name`, `unauthorized worker`, or an immediate socket close
- `pyminer` stdout / `/var/log/piaxe.log` contains `{"id":3,"result":false,"error":[24,"Unauthorized worker",null]}` or similar JSON-RPC reject
- `mining.subscribe` succeeds (extranonce + difficulty returned), then `mining.authorize` fails — connection healthy, login isn't
- Pool dashboard shows 0 workers online despite the PiAxe drawing normal wattage and the BM1366 chip warming to 55-65 °C
- `pyminer` reconnects in a tight 5-30 second loop — accepts TCP, rejects auth, drops, reconnects, repeats
- No shares ever land at the pool, even after hours of "running" according to the host
- Local `pyminer` stdout shows ~450-500 GH/s while the pool sees zero accepted shares
- `config.json` `user_name` has no dot, two dots, a Lightning address, an email, or a username from a different pool
- `config.json` `password` is blank, contains `password`, or has a typo (most pools require a non-blank value, `x` is the stratum convention)
- Recently switched pools (`solo.ckpool.org` ↔ `public-pool.io`) and forgot to update worker name format and/or port at the same time
- Pool host resolves but every `mining.authorize` is silently dropped with no JSON error response — possible region/IP-range deny
Step-by-Step Fix
SSH to the Pi (`ssh pi@<piaxe-ip>`) or attach keyboard + monitor. Open `~/piaxe-miner/config.json` with `sudo nano`. Confirm `user_name` is `<on-chain-BTC-address>.<workername>` — exactly one literal dot, alphanumeric worker [a-zA-Z0-9_-]. Re-type the address by hand from your wallet (don't paste from PDF — zero-width characters break the parse). Use `bc1q...` native segwit for max pool compatibility. Save (Ctrl+O, Enter, Ctrl+X). `sudo systemctl restart piaxe`. Watch `journalctl -u piaxe -f` for 60 seconds — expect `mining.authorize` followed by `result: true`.
Set `"password": "x"` exactly in `config.json`. Lowercase, single character, no spaces, no escaping. Universal stratum placeholder accepted by `solo.ckpool.org`, `public-pool.io`, `pool.d-central.tech`. Unblocks Braiins Pool (which requires `x`, not blank) and silent-rejecting self-hosted MiningCore installs. For NiceHash use `"d=1024"` style difficulty hint per their docs. Save, restart `pyminer`.
Strip protocol prefixes from `host`. Should be a bare hostname like `solo.ckpool.org` — not `stratum+tcp://solo.ckpool.org`, not `https://...`, not a trailing slash. `port` should be a raw integer literal (`3333`), not a quoted string `"3333"`. Validate the JSON parses: `python3 -c "import json; print(json.load(open('config.json')))"`. If the print succeeds, the file is valid. Restart `pyminer`.
Validate the address part of `user_name` (everything before the first dot) on https://mempool.space. If the explorer returns "invalid address" or "address not found" (vs. found-with-zero-tx, which is fine for a fresh receive address), the address is malformed. Re-derive a fresh receive address from Sparrow / Electrum / a hardware wallet and replace it in `config.json`. A Lightning address (`name@domain.com`) is not on-chain — replace with a `bc1q` from the same wallet.
Switch to a known-permissive solo pool as a control. Set `host: public-pool.io`, `port: 21496`, `user_name: <your-bc1q-address>.piaxe-01`, `password: x`. Restart `pyminer`. If `public-pool.io` authorizes cleanly, your original pool has a policy you violated — most likely a username-required pool (Kano, F2Pool, Antpool style) that you mistook for an address-as-username solo pool. Stay on `public-pool.io` or switch to `solo.ckpool.org:3333` / `solo.d-central.tech` (verify D-Central's solo port on the pool page).
Capture and read the pool's exact JSON-RPC reject. Edit `/etc/systemd/system/piaxe.service`, add `StandardOutput=append:/var/log/piaxe.log` and `StandardError=append:/var/log/piaxe.log` under `[Service]`. `sudo systemctl daemon-reload && sudo systemctl restart piaxe`. Wait for one auth-fail cycle. `grep -A1 authorize /var/log/piaxe.log`. Read the pool's error response. Code 24 = `Unauthorized worker`; code 23 = `Low difficulty share`; code 21 = `Job not found`. Code → field. Reference: https://en.bitcoin.it/wiki/Stratum_mining_protocol.
Test the same credentials from a desktop using `ncat` + a hand-crafted stratum payload. From a desktop: `ncat <pool-host> <pool-port>`, then paste `{"id":1,"method":"mining.subscribe","params":["test"]}` followed by `{"id":2,"method":"mining.authorize","params":["<your-user_name>","<your-password>"]}`. Pool replies inline. If desktop authorizes with the same credentials and the Pi doesn't, the bug is on the Pi side (encoding, hidden character, JSON escaping). If both fail, the credentials themselves are the problem.
Generate a fresh, unused receive address from a hardware wallet (Coldcard, Trezor, Ledger). Some pools have flagged specific addresses for chain-analysis false positives. A brand-new address from a hardware wallet is the cleanest test. Update `config.json`, restart, retry. If the new address authorizes and the old one didn't, you have a flagged address — change `user_name` to a derived child address and continue.
Test for region / IP block. Repeat the desktop `ncat` test from a *different* ISP (mobile hotspot is fine). If both desktop tests succeed and only the Pi fails, the Pi has a network-side issue (Step 10). If the Pi succeeds via mobile hotspot but fails on home WiFi, your home ISP/router is mangling packets. If only one specific pool fails everywhere, that pool has region-blocked your IP range — switch pool.
Force IPv4 on the Pi. Some pool stratum servers don't bind on IPv6 and `pyminer` resolves AAAA before A records. Append to `/etc/sysctl.conf`: `net.ipv6.conf.all.disable_ipv6=1` and `net.ipv6.conf.default.disable_ipv6=1`. Apply with `sudo sysctl -p`. Restart `pyminer`. Some PiAxe community-reported auth-fail loops are pure IPv6/IPv4 negotiation bugs that disappear when forcing v4-only.
Capture a pcap of the auth handshake. `sudo tcpdump -i wlan0 -w /tmp/piaxe-auth.pcap host <pool-host> and port <pool-port>`. Restart `pyminer` so a fresh attempt happens. Stop after 60 seconds. Open the pcap in Wireshark on a desktop. Filter on the pool host. Read the JSON payloads of `mining.subscribe` and `mining.authorize`. Look for: extra whitespace, smart quotes, missing newline, doubled `rn`. The stratum RFC requires `n` line terminators; some `pyminer` forks shipped `rn` and broke strict parsers.
Read `~/piaxe-miner/stratum.py` line-by-line. Find the `mining.authorize` send. Confirm the format-string the code uses to assemble params. If it does string concatenation rather than `json.dumps`, you risk shipping unescaped characters. If you see `\.` (escaped dot) in a params field, the Python escaping is mangling your worker suffix. The whole `pyminer` is under 2,000 lines of readable Python — auditable in an evening.
Pin `piaxe-miner` to a known-good upstream commit. `cd ~/piaxe-miner && git log --oneline stratum.py`. Identify a commit other operators reported stable (cross-reference https://osmu.wiki/piaxe/about/). `git checkout <commit>`. Restart `pyminer`. If auth returns to working on an older commit, HEAD has a regression — file at https://github.com/shufps/piaxe-miner/issues with bisect result, redacted `config.json`, and pcap excerpt.
Cross-test against `cgminer` or `bfgminer` on a desktop. Both have battle-tested stratum auth handling. Configure with the same `host/port/user_name/password`, run for 60 seconds. If `cgminer` authorizes cleanly with credentials that fail in `pyminer`, the bug is in `pyminer`'s `stratum.py`. Reference: https://github.com/luke-jr/bfgminer for the C-side stratum implementation.
Stop DIY and escalate. You've applied Steps 1-14, ruled out config / address / pool / network / IPv6 / Python source, and a pcap shows `pyminer` sending a clean `mining.authorize` with the pool returning silent FIN or an undocumented `result: false`. Open a D-Central support ticket at https://d-central.tech/contact/ with: pcap excerpt, redacted `config.json`, `journalctl -u piaxe -n 500`, and your `piaxe-miner` git commit hash. For confirmed upstream bugs, also file at https://github.com/shufps/piaxe-miner/issues — D-Central will triage the config + hardware side in one ticket.
If after Steps 1-15 the conclusion is a Pi-side hardware fault (rare — corrupt SD image or bad ethernet/WiFi PHY on a specific Pi 4 SKU), pack the PiAxe (Pi + BM1366 hat) in anti-static bags, double-box with ≥5 cm foam on every side, and ship to D-Central. Include a printed note with: pcap analysis result, observed pool error code, last-known-good `pyminer` commit hash, your contact info. Standard ASIC repair turnaround applies — 5-10 business days; we'll re-image the Pi, replace it, or escalate to upstream.
When to Seek Professional Repair
If the steps above do not resolve the issue, or if you are not comfortable performing these repairs yourself, professional service is recommended. Attempting advanced repairs without proper equipment can cause further damage.
Related Error Codes
Still Having Issues?
Our team of Bitcoin Mining Hackers has been repairing ASIC miners since 2016. We have seen it all and fixed it all. Get a professional diagnosis.
