{"record":{"id":"6dca974dd2f96dda","repo":"fish2018/pansou","slug":"http-d-6dca97","errorCode":null,"errorMessage":"HTTP 状态码 %d","messagePattern":"HTTP 状态码 (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/nsgame/nsgame.go","lineNumber":506,"sourceCode":"\t\t\t// 指数退避重试\n\t\t\tbackoff := time.Duration(1<<uint(i-1)) * 200 * time.Millisecond\n\t\t\ttime.Sleep(backoff)\n\t\t}\n\n\t\t// 克隆请求避免并发问题\n\t\treqClone := req.Clone(req.Context())\n\n\t\tresp, err := client.Do(reqClone)\n\t\tif err == nil && resp.StatusCode == 200 {\n\t\t\treturn resp, nil\n\t\t}\n\n\t\tif resp != nil {\n\t\t\tresp.Body.Close()\n\t\t}\n\t\tlastErr = err\n\t\tif lastErr == nil {\n\t\t\tlastErr = fmt.Errorf(\"HTTP 状态码 %d\", resp.StatusCode)\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)\n}\n","sourceCodeStart":488,"sourceCodeEnd":512,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/nsgame/nsgame.go#L488-L512","documentation":"In nsgame's doRequestWithRetry, when the underlying request produces an error after exhausting retries, this generic 'HTTP 状态码 %d' error is constructed as the lastErr. The code has a logic bug: lastErr is assigned err immediately before, so the nil check never fires and this message is effectively dead code — errors surfaced this way almost always come from err, not the status code.","triggerScenarios":"Inside the retry loop, client.Do fails (or a non-OK status sets err) on every attempt; lastErr = err executes and the following 'if lastErr == nil' branch that would create this status-code error is unreachable.","commonSituations":"Search/detail requests repeatedly failing against nsthwj.cn — site down, rate-limited, or network broken — then wrapped by error 463 ('重试 %d 次后仍然失败').","solutions":["Inspect the wrapped lastErr in the final '重试 %d 次后仍然失败' error to find the real cause.","Fix the logic: check resp.StatusCode != http.StatusOK explicitly in the loop and build the status error there, since lastErr = err makes the nil check dead code.","Verify site reachability with curl and add a proxy if needed.","Reduce retry pressure (longer backoff) if the server is rate-limiting (429)."],"exampleFix":"// before\nlastErr = err\nif lastErr == nil {\n    lastErr = fmt.Errorf(\"HTTP 状态码 %d\", resp.StatusCode)\n}\n// after\nif err != nil {\n    lastErr = err\n} else if resp.StatusCode != http.StatusOK {\n    lastErr = fmt.Errorf(\"HTTP 状态码 %d\", resp.StatusCode)\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"_, err := doRequestWithRetry(req, client)\nif err != nil {\n    root := errors.Unwrap(err)\n    log.Printf(\"all retries exhausted, root cause: %v\", root)\n}","preventionTips":["Fix the dead-code branch: check resp.StatusCode != http.StatusOK explicitly in the loop.","Record the status code into lastErr so the final wrapped error is informative.","Use exponential backoff with jitter rather than fixed short sleeps.","Alert on repeated retry-exhaustion — it usually means the site is down or you're banned."],"tags":["http","retry","status-code","go"],"backgroundTag":"http-non-200-response","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"}