{"record":{"id":"97cdba7c1d7c680b","repo":"fish2018/pansou","slug":"anubis-w-97cdba","errorCode":null,"errorMessage":"解析 Anubis 验证题目失败: %w","messagePattern":"解析 Anubis 验证题目失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/miosou/miosou.go","lineNumber":262,"sourceCode":"type anubisChallengeDocument struct {\n\tRules struct {\n\t\tAlgorithm  string `json:\"algorithm\"`\n\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():","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/miosou/miosou.go#L244-L280","documentation":"parseAnubisChallenge extracts the challenge JSON from the gate page via regex and unmarshals it into anubisChallengeDocument after HTML-unescaping. This error wraps a json.Unmarshal failure (miosou.go:262) — the embedded JSON does not match the expected schema.","triggerScenarios":"The regex matched a challenge blob but json.Unmarshal fails: Anubis changed the JSON shape (renamed fields rules/challenge/id/randomData/algorithm/difficulty), HTML entity decoding left invalid JSON, or the body was truncated/corrupted.","commonSituations":"An Anubis server upgrade changing the challenge document format; a proxy/CDN mangling or truncating the page; a localized or customized Anubis deployment emitting different JSON.","solutions":["Update the anubisChallengeDocument struct tags to match the current Anubis challenge JSON schema.","Log the raw matched blob (html.UnescapeString(match[1])) to see the actual format and diff it against the struct.","Verify the response was not truncated (1 MiB LimitReader) and no proxy rewrote the page.","Run TestParseAndSolveAnubisChallenge with a fixture captured from the live server to confirm the parser."],"exampleFix":"// before\ntype anubisChallengeDocument struct {\n    Rules struct {\n        Algorithm  string `json:\"algorithm\"`\n        Difficulty int    `json:\"difficulty\"`\n    } `json:\"rules\"`\n    ...\n}\n// after — align tags with the server's current schema, e.g.\ntype anubisChallengeDocument struct {\n    Rules struct {\n        Algorithm  string `json:\"algorithm\"`\n        Difficulty int    `json:\"difficulty\"`\n    } `json:\"rules\"`\n    Challenge struct {\n        ID         string `json:\"id\"`\n        RandomData string `json:\"random_data\"` // renamed upstream\n    } `json:\"challenge\"`\n}","handlingStrategy":"validation","validationCode":"var probe map[string]any\nblob := html.UnescapeString(string(match[1]))\nif err := json.Unmarshal([]byte(blob), &probe); err != nil {\n    return fmt.Errorf(\"challenge blob is not valid JSON: %w\", err)\n}\nif _, ok := probe[\"challenge\"]; !ok || _, ok := probe[\"rules\"]; !ok {\n    return fmt.Errorf(\"challenge JSON missing expected keys\")\n}","typeGuard":"func looksLikeAnubisChallenge(blob string) bool {\n    var probe struct {\n        Rules     map[string]any `json:\"rules\"`\n        Challenge map[string]any `json:\"challenge\"`\n    }\n    return json.Unmarshal([]byte(blob), &probe) == nil &&\n        probe.Rules != nil && probe.Challenge != nil\n}","tryCatchPattern":"challenge, found, err := parseAnubisChallenge(body)\nif err != nil {\n    if strings.Contains(err.Error(), \"解析 Anubis 验证题目失败\") {\n        // schema drift: log raw blob and update struct tags\n    }\n    return err\n}","preventionTips":["Keep anubisChallengeDocument tags in sync with upstream Anubis","Capture and test against real gate-page fixtures (TestParseAndSolveAnubisChallenge)","Log the raw matched blob on failure","Watch for proxy/CDN page rewriting"],"tags":["json","anubis","parsing","schema"],"backgroundTag":"json-unmarshal-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"}