fish2018/pansou · error

无法完成机器人验证

Error message

无法完成机器人验证

What it means

After all workers exhaust the nonce search space (0..Diff), the solver checks whether every target hash was matched. This error is returned when at least one target hash was never found, i.e. no nonce in [0, Diff] produces a SHA-256(nonce+salt) equal to it, so verification cannot be submitted.

Solutions

  1. Re-fetch a fresh challenge and retry once; a stale challenge with mismatched targets is the usual cause
  2. Verify Diff actually bounds the answer: log Diff and the unsolved target hashes; if the site increased the range, raise the nonce upper bound accordingly
  3. Check whether the hash input format changed (e.g. salt+nonce vs nonce+salt, or hex vs raw salt) and update the worker accordingly
  4. If the site switched to the PoW scheme, dispatch to solvePowChallenge instead

Example fix

// before
hashInput = strconv.AppendInt(hashInput[:0], int64(nonce), 10)
hashInput = append(hashInput, saltBytes...)
// after (also try salt-prefixed form if targets remain unsolved)
hashInput = strconv.AppendInt(hashInput[:0], int64(nonce), 10)
hashInput = append(hashInput, saltBytes...)
// or: append(saltBytes, hashInput...) — confirm against site JS
Defensive patterns

Strategy: retry

Validate before calling

// no pre-call check can fully prevent this; ensure the challenge is fresh:
if time.Since(challengeFetchedAt) > challengeTTL { re-fetch before solving }

Try / catch

if err := p.solveLegacyHashChallenge(scraper, requestURL, challenge); err != nil {
    if strings.Contains(err.Error(), "无法完成机器人验证") {
        return p.refetchAndSolve(scraper, requestURL) // one retry with a fresh challenge
    }
    return err
}

Prevention

When it happens

Trigger: solveLegacyHashChallenge completes its brute force but solved != targetsLen and remaining is non-empty — some target hashes have no preimage within the searched nonce range.

Common situations: The site raised Diff or changed the hashing scheme (different salt composition or hash input) while the client still searches the old range; the challenge targets include hashes outside the client's nonce space; clock/skew-independent stale challenges where targets no longer match the salt.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/e5669775d645a434. Report an issue: GitHub.

Appendix: source

Thrown at plugin/gying/gying.go:1853

					}
					if solved.Load() >= targetsLen {
						mu.Unlock()
						return
					}
				}
				mu.Unlock()
			}
		}(workerID)
	}

	wg.Wait()

	if solved.Load() != targetsLen {
		mu.Lock()
		missing := len(remaining)
		mu.Unlock()
		if missing > 0 {
			return fmt.Errorf("无法完成机器人验证")
		}
	}

	form := url.Values{}
	form.Set("action", "verify")
	form.Set("id", challenge.ID)
	for _, nonce := range nonces {
		form.Add("nonce[]", strconv.Itoa(nonce))
	}

	return p.submitChallengeVerification(scraper, requestURL, form)
}

func (p *GyingPlugin) submitChallengeVerification(scraper *cloudscraper.Scraper, requestURL string, form url.Values) error {
	resp, err := scraper.Post(requestURL, "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
	if err != nil {
		return fmt.Errorf("提交验证失败: %w", err)
	}

View on GitHub (pinned to beaa561337)