mining.set_difficulty and Error Handling: When Things Go Wrong
Mining doesn’t always go smoothly. Connections drop, shares get rejected, and sometimes the pool changes the rules mid-game. Two mechanisms handle these situations: mining.set_difficulty manages the work intensity, and the error system tells you what went wrong.
mining.set_difficulty: Tuning the Throttle
Section titled “mining.set_difficulty: Tuning the Throttle”When you first connect to a pool, it assigns you an initial share difficulty. But that difficulty isn’t permanent — the pool continuously adjusts it based on your hashrate. This dynamic adjustment is called vardiff (variable difficulty).
The message
Section titled “The message”{ "id": null, "method": "mining.set_difficulty", "params": [8192]}That single number (8192 in this example) is the new share difficulty. It takes effect starting with the next mining.notify job — shares already in progress use the previous difficulty.
Why vardiff exists
Section titled “Why vardiff exists”Imagine a pool that set the same difficulty for every miner. An S21 at 200 TH/s would produce thousands of shares per second, flooding the pool with data. Meanwhile, an older S9 at 14 TH/s would barely submit one share per minute. Neither situation is ideal.
Vardiff solves this by adjusting each miner’s difficulty so that everyone submits shares at roughly the same rate — typically one share every few seconds.
- Your hashrate goes up (maybe you overclocked) → the pool raises your difficulty → fewer shares per second, but each share represents more work
- Your hashrate drops (a hash board failed) → the pool lowers your difficulty → more shares per second, each representing less work
- Total payout stays the same either way. Higher difficulty means fewer shares but each one is worth more. Lower difficulty means more shares but each one is worth less.
How the pool decides
Section titled “How the pool decides”Most pools target a specific share submission rate, like one share every 5-10 seconds. The pool monitors your actual submission rate and adjusts:
- Submitting too fast → pool doubles or quadruples difficulty
- Submitting too slowly → pool halves difficulty
- Some pools adjust gradually, others in larger jumps
The algorithm varies by pool, but the goal is the same: keep the share flow manageable without sacrificing measurement accuracy.
Error Handling
Section titled “Error Handling”When a mining.submit fails, the pool responds with an error instead of true. The error format follows JSON-RPC conventions:
{ "id": 4, "result": null, "error": [error_code, "error_message", null]}Error code reference
Section titled “Error code reference”Here are the standard Stratum error codes:
| Code | Name | What it means |
|---|---|---|
| 20 | Other/Unknown | A catch-all for unclassified errors. Could be anything. |
| 21 | Job not found | The job_id in your submission doesn’t match any active job on the pool. Usually means the job expired (new block was found). |
| 22 | Duplicate share | You’ve already submitted a share with this exact nonce/extranonce2/ntime combination. Something is wrong with your nonce iteration. |
| 23 | Low difficulty share | The hash you submitted doesn’t meet the current share difficulty target. Possible firmware bug or difficulty synchronization issue. |
| 24 | Unauthorized worker | The worker name in your submission wasn’t authorized via mining.authorize, or authorization expired. |
| 25 | Not subscribed | You’re trying to submit work before completing the mining.subscribe handshake. |
Error 21: Job not found (the most common)
Section titled “Error 21: Job not found (the most common)”This is by far the most frequent error, and it’s usually not a problem. Here’s what happens:
- Pool sends job “a1” via
mining.notify - Your miner starts working on job “a1”
- Someone on the network finds a new block
- Pool sends job “a2” with
clean_jobs = true - Your miner submits a share for job “a1” that was computed just before the new job arrived
- Pool responds: error 21, job not found — because job “a1” has been discarded
This is the stale share scenario. It’s normal and unavoidable due to network latency. A stale rate of 0.5-2% is typical. If you see higher than 5%, check your network connection to the pool.
Error 22: Duplicate share
Section titled “Error 22: Duplicate share”This means you submitted the same nonce for the same job twice. Causes:
- Firmware bug that resets nonce iteration
- Two miners sharing the same extraNonce (misconfiguration)
- Extremely rare: actual collision (shouldn’t happen with properly functioning hardware)
If you see persistent duplicate share errors, check that each miner has a unique worker name and that your firmware is up to date.
Error 23: Low difficulty
Section titled “Error 23: Low difficulty”The hash you submitted doesn’t meet the pool’s difficulty target. This usually happens when:
- Your miner received a
mining.set_difficultybut applied it to the wrong job - Firmware bug in difficulty comparison
- Corrupted data in transit
A handful of these is normal. Persistent error 23s indicate a hardware or firmware problem.
Connection Failures and Reconnection
Section titled “Connection Failures and Reconnection”TCP connections don’t last forever. Your miner-to-pool connection can drop for many reasons: internet outage, pool server restart, router timeout, or even a flaky Ethernet cable.
What happens when the connection drops
Section titled “What happens when the connection drops”- Your miner detects the TCP socket is closed (or stops receiving data)
- All in-flight work becomes worthless — it can’t be submitted
- The miner must establish a completely new connection
- New connection means: TCP handshake →
mining.configure→mining.subscribe→mining.authorize→ wait formining.set_difficulty+mining.notify - Only then can mining resume
Reconnection strategies
Section titled “Reconnection strategies”Exponential backoff: Don’t hammer the pool server with reconnection attempts. A good pattern is:
- 1st retry: wait 1 second
- 2nd retry: wait 2 seconds
- 3rd retry: wait 4 seconds
- 4th retry: wait 8 seconds
- …up to a maximum of ~60 seconds
This prevents your miner from overwhelming a struggling pool server and gives the network time to recover.
Backup pools: This is why your miner has Pool 2 and Pool 3 settings. If the primary pool is unreachable after a few retries, switch to the backup. Most miner firmware handles this automatically:
- Try Pool 1 (primary) — if it fails after 3-5 attempts…
- Switch to Pool 2 (backup) — mine there until Pool 1 recovers
- Periodically try Pool 1 again — switch back when it’s up
Keepalive
Section titled “Keepalive”Some pools and firewalls drop idle connections. To prevent this, miners can send periodic keepalive messages. While not part of the official Stratum spec, many implementations support it — either as empty lines or periodic mining.subscribe pings.
Putting It All Together
Section titled “Putting It All Together”A healthy Stratum session looks like this:
- Connect → subscribe → configure → authorize (once)
- Receive
mining.set_difficulty(periodically) - Receive
mining.notify→ work →mining.submit→ accepted (continuous loop) - Occasional stale shares (error 21) (normal, ~1%)
- Reconnect on connection drop (rare, handled automatically)
When things go wrong, the error codes tell you exactly what happened. Most issues resolve themselves — the miner reconnects, gets new work, and carries on. Persistent errors point to configuration problems, network issues, or failing hardware that need your attention.