{"record":{"id":"35463de6057dae27","repo":"fish2018/pansou","slug":"error-35463d","errorCode":null,"errorMessage":"未知请求错误","messagePattern":"未知请求错误","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"plugin/xdpan/xdpan.go","lineNumber":459,"sourceCode":"\t\treqClone := req.Clone(req.Context())\n\n\t\tresp, err := client.Do(reqClone)\n\t\tif err != nil {\n\t\t\tlastErr = err\n\t\t\tcontinue\n\t\t}\n\t\tif strings.EqualFold(resp.Header.Get(\"cf-mitigated\"), \"challenge\") {\n\t\t\tresp.Body.Close()\n\t\t\treturn nil, fmt.Errorf(\"站点 %s 已迁移并启用 Cloudflare 浏览器验证，当前服务端请求无法通过\", p.baseURL)\n\t\t}\n\t\tif resp.StatusCode == http.StatusOK {\n\t\t\treturn resp, nil\n\t\t}\n\t\tlastErr = fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t\tresp.Body.Close()\n\t}\n\tif lastErr == nil {\n\t\tlastErr = fmt.Errorf(\"未知请求错误\")\n\t}\n\treturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", MaxRetries, lastErr)\n}\n\n// setRequestHeaders 设置请求头\nfunc (p *XdpanPlugin) setRequestHeaders(req *http.Request) {\n\treq.Header.Set(\"User-Agent\", UserAgent)\n\treq.Header.Set(\"Referer\", strings.TrimRight(p.baseURL, \"/\")+\"/?p=baidu\")\n\treq.Header.Set(\"Accept\", \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\")\n\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\treq.Header.Set(\"Connection\", \"keep-alive\")\n\treq.Header.Set(\"Cache-Control\", \"max-age=0\")\n}\n\n// cacheItem 缓存项结构\ntype cacheItem struct {\n\tlinks     []model.Link\n\ttimestamp time.Time","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xdpan/xdpan.go#L441-L477","documentation":"Defensive fallback in doRequestWithRetry: if the retry loop finished without recording any error (a code path that should be unreachable because every non-200 sets lastErr), lastErr is initialized to this 'unknown request error' message before the retry-exhausted wrapper is returned.","triggerScenarios":"Retry loop exits with lastErr still nil — e.g. loop structure changes or MaxRetries <= 0 so no attempt is made.","commonSituations":"Misconfiguration where MaxRetries is 0 or negative, causing the for-loop body never to execute; future refactors altering the loop.","solutions":["Ensure MaxRetries is a positive constant","Validate retry count at plugin init","Keep the guard but include MaxRetries in the final wrapped message for diagnosis"],"exampleFix":"// before\nif lastErr == nil {\n    lastErr = fmt.Errorf(\"未知请求错误\")\n}\n// after\nif lastErr == nil {\n    lastErr = fmt.Errorf(\"未知请求错误 (MaxRetries=%d)\", MaxRetries)\n}","handlingStrategy":"validation","validationCode":"if MaxRetries <= 0 {\n    return errors.New(\"MaxRetries 必须为正数\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"未知请求错误\") {\n    log.Printf(\"重试循环未执行任何有效尝试, MaxRetries=%d\", MaxRetries)\n}","preventionTips":["Keep MaxRetries strictly positive","Add a unit test covering zero-retry configuration","Treat this error as a bug report trigger, not a user-facing issue"],"tags":["retry","defensive","internal"],"backgroundTag":"internal-invariant-violation","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"}