fish2018/pansou · error

不支持的 Anubis 验证算法

Error message

不支持的 Anubis 验证算法: %s

What it means

Anubis challenges can use 'fast' or 'slow' hashing algorithms; this plugin implements only SHA-256 proof-of-work. If Rules.Algorithm is anything else, parseAnubisChallenge returns this error (miosou.go:268) because the solver cannot compute a valid proof.

Solutions

  1. Upgrade the plugin (or Anubis on the server side) so both ends support the same algorithm set.
  2. If you control the server, reconfigure Anubis to use the "fast" algorithm.
  3. Extend solveAnubisChallenge to implement the new algorithm and relax the check in parseAnubisChallenge.
  4. Pin the server to an Anubis version compatible with this client.

Example fix

// before
if challenge.Rules.Algorithm != "fast" && challenge.Rules.Algorithm != "slow" {
    return anubisChallengeDocument{}, true, fmt.Errorf("不支持的 Anubis 验证算法: %s", challenge.Rules.Algorithm)
}
// after
if challenge.Rules.Algorithm != "fast" && challenge.Rules.Algorithm != "slow" {
    return anubisChallengeDocument{}, true, fmt.Errorf("不支持的 Anubis 验证算法: %s (请升级客户端或服务端)", challenge.Rules.Algorithm)
}
Defensive patterns

Strategy: validation

Validate before calling

var probe struct {
    Rules struct {
        Algorithm string `json:"algorithm"`
    } `json:"rules"`
}
if err := json.Unmarshal([]byte(html.UnescapeString(blob)), &probe); err == nil {
    if probe.Rules.Algorithm != "fast" && probe.Rules.Algorithm != "slow" {
        return fmt.Errorf("unsupported Anubis algorithm: %s", probe.Rules.Algorithm)
    }
}

Type guard

func supportedAlgorithm(algo string) bool {
    return algo == "fast" || algo == "slow"
}

Try / catch

challenge, found, err := parseAnubisChallenge(body)
if err != nil {
    if strings.Contains(err.Error(), "不支持的 Anubis 验证算法") {
        // version mismatch: upgrade client or reconfigure server, don't blind-retry
    }
    return err
}

Prevention

When it happens

Trigger: The gate page's challenge JSON carries an algorithm value other than "fast"/"slow" (e.g. a future Anubis release introducing a new algorithm like argon2 or cuckoo filter mode).

Common situations: The upstream Anubis project adds a new proof algorithm; a customized Anubis deployment configured with an unsupported algorithm; a typo'd/corrupt algorithm field from a mangled page.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at plugin/miosou/miosou.go:268

		ID         string `json:"id"`
		RandomData string `json:"randomData"`
	} `json:"challenge"`
}

func parseAnubisChallenge(body []byte) (anubisChallengeDocument, bool, error) {
	match := anubisChallengePattern.FindSubmatch(body)
	if len(match) != 2 {
		return anubisChallengeDocument{}, false, nil
	}
	var challenge anubisChallengeDocument
	if err := json.Unmarshal([]byte(html.UnescapeString(string(match[1]))), &challenge); err != nil {
		return anubisChallengeDocument{}, true, fmt.Errorf("解析 Anubis 验证题目失败: %w", err)
	}
	if challenge.Challenge.ID == "" || challenge.Challenge.RandomData == "" || challenge.Rules.Difficulty < 1 || challenge.Rules.Difficulty > 7 {
		return anubisChallengeDocument{}, true, fmt.Errorf("Anubis 验证题目无效")
	}
	if challenge.Rules.Algorithm != "fast" && challenge.Rules.Algorithm != "slow" {
		return anubisChallengeDocument{}, true, fmt.Errorf("不支持的 Anubis 验证算法: %s", challenge.Rules.Algorithm)
	}
	return challenge, true, nil
}

func solveAnubisChallenge(ctx context.Context, randomData string, difficulty int) (string, uint64, error) {
	prefix := []byte(randomData)
	buffer := make([]byte, len(prefix), len(prefix)+20)
	copy(buffer, prefix)
	for nonce := uint64(0); ; nonce++ {
		if nonce&4095 == 0 {
			select {
			case <-ctx.Done():
				return "", 0, fmt.Errorf("计算 Anubis 工作量证明失败: %w", ctx.Err())
			default:
			}
		}
		candidate := strconv.AppendUint(buffer[:len(prefix)], nonce, 10)
		hash := sha256.Sum256(candidate)

View on GitHub (pinned to beaa561337)