{"record":{"id":"c70ba61dadb176ea","repo":"fish2018/pansou","slug":"anubis","errorCode":null,"errorMessage":"Anubis 验证题目无效","messagePattern":"Anubis 验证题目无效","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/miosou/miosou.go","lineNumber":265,"sourceCode":"\t\tDifficulty int    `json:\"difficulty\"`\n\t} `json:\"rules\"`\n\tChallenge struct {\n\t\tID         string `json:\"id\"`\n\t\tRandomData string `json:\"randomData\"`\n\t} `json:\"challenge\"`\n}\n\nfunc parseAnubisChallenge(body []byte) (anubisChallengeDocument, bool, error) {\n\tmatch := anubisChallengePattern.FindSubmatch(body)\n\tif len(match) != 2 {\n\t\treturn anubisChallengeDocument{}, false, nil\n\t}\n\tvar challenge anubisChallengeDocument\n\tif err := json.Unmarshal([]byte(html.UnescapeString(string(match[1]))), &challenge); err != nil {\n\t\treturn anubisChallengeDocument{}, true, fmt.Errorf(\"解析 Anubis 验证题目失败: %w\", err)\n\t}\n\tif challenge.Challenge.ID == \"\" || challenge.Challenge.RandomData == \"\" || challenge.Rules.Difficulty < 1 || challenge.Rules.Difficulty > 7 {\n\t\treturn anubisChallengeDocument{}, true, fmt.Errorf(\"Anubis 验证题目无效\")\n\t}\n\tif challenge.Rules.Algorithm != \"fast\" && challenge.Rules.Algorithm != \"slow\" {\n\t\treturn anubisChallengeDocument{}, true, fmt.Errorf(\"不支持的 Anubis 验证算法: %s\", challenge.Rules.Algorithm)\n\t}\n\treturn challenge, true, nil\n}\n\nfunc solveAnubisChallenge(ctx context.Context, randomData string, difficulty int) (string, uint64, error) {\n\tprefix := []byte(randomData)\n\tbuffer := make([]byte, len(prefix), len(prefix)+20)\n\tcopy(buffer, prefix)\n\tfor nonce := uint64(0); ; nonce++ {\n\t\tif nonce&4095 == 0 {\n\t\t\tselect {\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn \"\", 0, fmt.Errorf(\"计算 Anubis 工作量证明失败: %w\", ctx.Err())\n\t\t\tdefault:\n\t\t\t}","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/miosou/miosou.go#L247-L283","documentation":"After unmarshalling, parseAnubisChallenge validates the challenge: id and randomData must be non-empty and difficulty must be 1–7. Otherwise it returns this sentinel error (miosou.go:265), meaning the challenge parsed but is unusable.","triggerScenarios":"JSON unmarshals cleanly into anubisChallengeDocument but Challenge.ID or Challenge.RandomData is empty, or Rules.Difficulty is 0 or >7 — i.e. field-name drift or an upstream format change rather than corrupt JSON.","commonSituations":"Anubis raising its difficulty range or renaming fields so they unmarshal to zero values; a stub/test Anubis deployment emitting minimal JSON; a proxy serving a cached/partial page.","solutions":["Dump the unmarshalled document to see which field is empty/out-of-range and update struct tags if Anubis renamed it.","Widen the accepted difficulty range only if the upstream server legitimately changed bounds.","Confirm the server is a real Anubis instance and not a custom/modified deployment.","Retry — if it's a transiently corrupted page, ensureGate's retries may fetch a clean one."],"exampleFix":"// before\nif challenge.Challenge.ID == \"\" || challenge.Challenge.RandomData == \"\" || challenge.Rules.Difficulty < 1 || challenge.Rules.Difficulty > 7 {\n    return anubisChallengeDocument{}, true, fmt.Errorf(\"Anubis 验证题目无效\")\n}\n// after — log which invariant failed for diagnosability\nif challenge.Challenge.ID == \"\" || challenge.Challenge.RandomData == \"\" || challenge.Rules.Difficulty < 1 || challenge.Rules.Difficulty > 7 {\n    return anubisChallengeDocument{}, true, fmt.Errorf(\"Anubis 验证题目无效: id=%q randomData=%q difficulty=%d\",\n        challenge.Challenge.ID, challenge.Challenge.RandomData, challenge.Rules.Difficulty)\n}","handlingStrategy":"validation","validationCode":"var probe struct {\n    Challenge struct {\n        ID         string `json:\"id\"`\n        RandomData string `json:\"randomData\"`\n    } `json:\"challenge\"`\n    Rules struct {\n        Difficulty int `json:\"difficulty\"`\n    } `json:\"rules\"`\n}\nif err := json.Unmarshal([]byte(html.UnescapeString(blob)), &probe); err != nil {\n    return err\n}\nif probe.Challenge.ID == \"\" || probe.Challenge.RandomData == \"\" || probe.Rules.Difficulty < 1 || probe.Rules.Difficulty > 7 {\n    return fmt.Errorf(\"challenge fields missing or difficulty out of range\")\n}","typeGuard":"func validAnubisChallenge(c anubisChallengeDocument) bool {\n    return c.Challenge.ID != \"\" && c.Challenge.RandomData != \"\" &&\n        c.Rules.Difficulty >= 1 && c.Rules.Difficulty <= 7\n}","tryCatchPattern":"challenge, found, err := parseAnubisChallenge(body)\nif err != nil {\n    if strings.Contains(err.Error(), \"验证题目无效\") {\n        // server format drift: log document and verify struct tags\n    }\n    return err\n}","preventionTips":["Validate challenge fields before starting the PoW loop","Log which invariant failed (id/randomData/difficulty)","Test the parser against captured fixtures from the live server","Confirm the server runs stock Anubis"],"tags":["anubis","validation","parsing","anti-bot"],"backgroundTag":"schema-validation-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}