Skip to content

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).

{
"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.

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.

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.

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]
}

Here are the standard Stratum error codes:

CodeNameWhat it means
20Other/UnknownA catch-all for unclassified errors. Could be anything.
21Job not foundThe job_id in your submission doesn’t match any active job on the pool. Usually means the job expired (new block was found).
22Duplicate shareYou’ve already submitted a share with this exact nonce/extranonce2/ntime combination. Something is wrong with your nonce iteration.
23Low difficulty shareThe hash you submitted doesn’t meet the current share difficulty target. Possible firmware bug or difficulty synchronization issue.
24Unauthorized workerThe worker name in your submission wasn’t authorized via mining.authorize, or authorization expired.
25Not subscribedYou’re trying to submit work before completing the mining.subscribe handshake.

This is by far the most frequent error, and it’s usually not a problem. Here’s what happens:

  1. Pool sends job “a1” via mining.notify
  2. Your miner starts working on job “a1”
  3. Someone on the network finds a new block
  4. Pool sends job “a2” with clean_jobs = true
  5. Your miner submits a share for job “a1” that was computed just before the new job arrived
  6. 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.

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.

The hash you submitted doesn’t meet the pool’s difficulty target. This usually happens when:

  • Your miner received a mining.set_difficulty but 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.

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.

  1. Your miner detects the TCP socket is closed (or stops receiving data)
  2. All in-flight work becomes worthless — it can’t be submitted
  3. The miner must establish a completely new connection
  4. New connection means: TCP handshake → mining.configuremining.subscribemining.authorize → wait for mining.set_difficulty + mining.notify
  5. Only then can mining resume

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:

  1. Try Pool 1 (primary) — if it fails after 3-5 attempts…
  2. Switch to Pool 2 (backup) — mine there until Pool 1 recovers
  3. Periodically try Pool 1 again — switch back when it’s up

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.

A healthy Stratum session looks like this:

  1. Connect → subscribe → configure → authorize (once)
  2. Receive mining.set_difficulty (periodically)
  3. Receive mining.notify → work → mining.submit → accepted (continuous loop)
  4. Occasional stale shares (error 21) (normal, ~1%)
  5. 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.