{"record":{"id":"1117af151c9e6a62","repo":"fish2018/pansou","slug":"http-d-1117af","errorCode":null,"errorMessage":"HTTP %d","messagePattern":"HTTP %d","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/lingjisp/lingjisp.go","lineNumber":276,"sourceCode":"\t\t\t\tif n > 0 {\n\t\t\t\t\tdata = append(data, buffer[:n]...)\n\t\t\t\t}\n\t\t\t\tif readErr != nil {\n\t\t\t\t\tif strings.Contains(readErr.Error(), \"EOF\") {\n\t\t\t\t\t\tcancel()\n\t\t\t\t\t\treturn data, nil\n\t\t\t\t\t}\n\t\t\t\t\tlastErr = readErr\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif resp != nil {\n\t\t\t\tresp.Body.Close()\n\t\t\t}\n\t\t\tlastErr = err\n\t\t\tif lastErr == nil {\n\t\t\t\tlastErr = fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t\t\t}\n\t\t}\n\t\tcancel()\n\n\t\tif attempt < lingjiMaxRetries-1 {\n\t\t\ttime.Sleep(200 * time.Millisecond * time.Duration(1<<attempt))\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"重试 %d 次后失败: %w\", lingjiMaxRetries, lastErr)\n}\n\nfunc dedupeLingjiItems(items []lingjiVideoItem) []lingjiVideoItem {\n\tseen := make(map[int]struct{})\n\tresults := make([]lingjiVideoItem, 0, len(items))\n\n\tfor _, item := range items {\n\t\tid := chooseLingjiID(item)","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/lingjisp/lingjisp.go#L258-L294","documentation":"Inside doLingjiGET's retry loop, when a non-nil error occurred and lastErr ended up nil, the code fabricates a fallback error \"HTTP <status>\" from resp.StatusCode. This is a defensive branch for the case where the response indicated failure but no underlying error object was captured — it surfaces the numeric HTTP status as the failure reason.","triggerScenarios":"An attempt received an HTTP response whose status was treated as failure (non-2xx/expected), but err from the request was nil, so the loop synthesizes fmt.Errorf(\"HTTP %d\", resp.StatusCode) as lastErr — e.g. 403, 404, 429, 502 from the API.","commonSituations":"Upstream returns 429 during bursts of search/detail calls; API path changed yielding 404; WAF returns 403 to non-browser clients; gateway 502/504 during API downtime. The error then surfaces wrapped by 搜索请求失败/详情请求失败 after all retries.","solutions":["Check the status number in the message: 403→add browser headers, 429→slow down/backoff, 404→update API path, 5xx→retry later","Increase lingjiMaxRetries so transient 5xx/429 are retried with the existing exponential backoff","Send browser-like User-Agent/Referer headers to avoid 403 from WAF","Verify lingjiAPIBase URL is current if seeing 404","Handle the response status explicitly (return on expected statuses) instead of relying on the nil-err fallback"],"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 {\n    lastErr = fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n}\nif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {\n    cancel()\n    continue // retryable\n}\nreturn nil, lastErr // non-retryable, fail fast","handlingStrategy":"retry","validationCode":"// Pre-check expected status handling before the retry loop\nstatusOK := func(code int) bool { return code >= 200 && code < 300 }\nif resp != nil && !statusOK(resp.StatusCode) {\n    return classifyAndMaybeRetry(resp.StatusCode) // 429/5xx retry, 4xx fail fast\n}","typeGuard":null,"tryCatchPattern":"body, err := doLingjiGET(client, apiURL, timeout)\nif err != nil {\n    var httpErr interface{ HTTPStatus() int }\n    if errors.As(err, &httpErr) && httpErr.HTTPStatus() == http.StatusTooManyRequests {\n        time.Sleep(longerBackoff)\n        body, err = doLingjiGET(client, apiURL, timeout)\n    }\n    if err != nil {\n        return nil, err\n    }\n}","preventionTips":["Classify status codes: retry 429/5xx, fail fast on 4xx","Send browser-like headers to avoid 403s","Keep lingjiMaxRetries and the exponential backoff base tuned for burst traffic","Log the final status after all retries for monitoring"],"tags":["http","retry","status-code","api"],"backgroundTag":"http-error-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"}