{"record":{"id":"3490e997b5eab54e","repo":"fish2018/pansou","slug":"hunhepan-api-error-w","errorCode":null,"errorMessage":"hunhepan API error: %w","messagePattern":"hunhepan API error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/hunhepan/hunhepan.go","lineNumber":86,"sourceCode":"\n// doSearch 实际的搜索实现\nfunc (p *HunhepanAsyncPlugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tdebugLog(\"开始搜索，关键词: %s\", keyword)\n\t\n\t// 创建结果通道和错误通道\n\tresultChan := make(chan []HunhepanItem, 4)\n\terrChan := make(chan error, 4)\n\n\t// 创建等待组\n\tvar wg sync.WaitGroup\n\twg.Add(4)\n\n\t// 并行请求三个API\n\tgo func() {\n\t\tdefer wg.Done()\n\t\titems, err := p.searchAPI(client, HunhepanAPI, keyword)\n\t\tif err != nil {\n\t\t\terrChan <- fmt.Errorf(\"hunhepan API error: %w\", err)\n\t\t\treturn\n\t\t}\n\t\tresultChan <- items\n\t}()\n\n\tgo func() {\n\t\tdefer wg.Done()\n\t\titems, err := p.searchAPI(client, QkpansoAPI, keyword)\n\t\tif err != nil {\n\t\t\terrChan <- fmt.Errorf(\"qkpanso API error: %w\", err)\n\t\t\treturn\n\t\t}\n\t\tresultChan <- items\n\t}()\n\n\tgo func() {\n\t\tdefer wg.Done()\n\t\titems, err := p.searchAPI(client, KuakeAPI, keyword)","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/hunhepan/hunhepan.go#L68-L104","documentation":"The hunhepan plugin fires parallel goroutines against multiple upstream search APIs (HunhepanAPI, QkpansoAPI, KuakeAPI, MisosoAPI). When the goroutine calling p.searchAPI(client, HunhepanAPI, keyword) fails, it sends this wrapped error into errChan.","triggerScenarios":"p.searchAPI for the HunhepanAPI endpoint returns any error: HTTP request failure, non-2xx status, JSON decode failure, or empty/invalid response body during a keyword search.","commonSituations":"Hunhepan API endpoint changed or is down, API requires updated auth/cookies, request blocked by rate limiting, keyword triggers an upstream error response.","solutions":["Log the wrapped cause (errors.Unwrap) to see if it is transport, status, or decode failure","Verify the HunhepanAPI URL is still valid and the request payload matches the current API contract","Retry with backoff if the failure was transient (timeout/5xx)","Since results are aggregated from 4 APIs, treat this as partial failure and use results from the other endpoints","Check for API changes (docs/endpoint moved) if the error persists"],"exampleFix":"// before\nitems, err := p.searchAPI(client, HunhepanAPI, keyword)\nif err != nil {\n\terrChan <- fmt.Errorf(\"hunhepan API error: %w\", err)\n\treturn\n}\n// after\nitems, err := p.searchAPI(client, HunhepanAPI, keyword)\nif err != nil {\n\tlog.Printf(\"hunhepan API error (non-fatal): %v\", err) // degrade gracefully\n\treturn\n}\nresultChan <- items","handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isHunhepanAPIError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"hunhepan API error\")\n}","tryCatchPattern":"results, err := plugin.Search(keyword)\nif err != nil {\n\tif isHunhepanAPIError(err) {\n\t\t// aggregation may still return partial results from other sources\n\t\tlog.Printf(\"hunhepan source failed: %v\", err)\n\t}\n\treturn nil, err\n}","preventionTips":["Design callers to tolerate partial multi-source results","Monitor each upstream endpoint's health independently","Keep endpoint URLs and payload schemas updated against upstream changes","Rate-limit the parallel fan-out to avoid tripping upstream limits"],"tags":["api","network","upstream","concurrency"],"backgroundTag":"upstream-api-error","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"}