{"record":{"id":"aad36eaab78009b3","repo":"fish2018/pansou","slug":"http-d-aad36e","errorCode":null,"errorMessage":"HTTP状态码: %d","messagePattern":"HTTP状态码: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/ouge/ouge.go","lineNumber":412,"sourceCode":"\tif len(matches) > 1 {\n\t\treturn matches[1]\n\t}\n\treturn \"\"\n}\n\n// doRequestWithRetry 带重试的HTTP请求（优化JSON API的重试策略）\nfunc (p *OugeAsyncPlugin) doRequestWithRetry(req *http.Request, client *http.Client) (*http.Response, error) {\n\tmaxRetries := 2  // 对于JSON API减少重试次数\n\tvar lastErr error\n\t\n\tfor i := 0; i < maxRetries; i++ {\n\t\tresp, err := client.Do(req)\n\t\tif err == nil {\n\t\t\tif resp.StatusCode == http.StatusOK {\n\t\t\t\treturn resp, nil\n\t\t\t}\n\t\t\tresp.Body.Close()\n\t\t\tlastErr = fmt.Errorf(\"HTTP状态码: %d\", resp.StatusCode)\n\t\t} else {\n\t\t\tlastErr = err\n\t\t}\n\t\t\n\t\t// JSON API快速重试：只等待很短时间\n\t\tif i < maxRetries-1 {\n\t\t\ttime.Sleep(100 * time.Millisecond) // 从秒级改为100毫秒\n\t\t}\n\t}\n\t\n\treturn nil, fmt.Errorf(\"[%s] 请求失败，重试%d次后仍失败: %w\", p.Name(), maxRetries, lastErr)\n}\n\n// GetPerformanceStats 获取性能统计信息\nfunc (p *OugeAsyncPlugin) GetPerformanceStats() map[string]interface{} {\n\ttotalRequests := atomic.LoadInt64(&searchRequests)\n\ttotalTime := atomic.LoadInt64(&totalSearchTime)\n\t","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/ouge/ouge.go#L394-L430","documentation":"Internal error created by doRequestWithRetry when the server responded but with a non-200 status code. The response body is closed and the status is recorded as lastErr; if all retries fail with status errors, this becomes the wrapped cause of error 475. It is a sentinel describing the HTTP status, not a full error type.","triggerScenarios":"client.Do succeeds and resp.StatusCode != http.StatusOK on every retry attempt (e.g. 403, 429, 500, 502 from woog.nxog.eu.org); only the numeric status is kept, discarding the response body that may contain the real reason.","commonSituations":"IP rate-limited (429) by the API; Cloudflare/WAF challenge (403); upstream origin down behind a proxy (502/503); the site moved and old host returns 404.","solutions":["Capture and log a portion of the response body before closing it to learn why the status was non-200","Back off and retry later if the status is 429 (rate limited)","Rotate IP / use a proxy if 403 WAF blocks persist","Check whether the base URL https://woog.nxog.eu.org/ is still the correct endpoint"],"exampleFix":"// before\nresp.Body.Close()\nlastErr = fmt.Errorf(\"HTTP状态码: %d\", resp.StatusCode)\n// after\nsnippet, _ := io.ReadAll(io.LimitReader(resp.Body, 256))\nresp.Body.Close()\nlastErr = fmt.Errorf(\"HTTP状态码: %d, body=%.256s\", resp.StatusCode, snippet)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"HTTP状态码: 429\") {\n    time.Sleep(time.Duration(jitter(2, 10)) * time.Second)\n    return retry()\n}","preventionTips":["Throttle request rate to stay under the API's limits","Preserve the response body of failed statuses for diagnosis","Treat 5xx and 4xx differently: back off long on 429/403","Rotate proxies if WAF blocks persist"],"tags":["http","status-code","retry","plugin"],"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"}