{"record":{"id":"35cce650c703537f","repo":"fish2018/pansou","slug":"s-w-35cce6","errorCode":null,"errorMessage":"[%s] 执行搜索失败: %w","messagePattern":"\\[(.+?)\\] 执行搜索失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/dyyj/dyyj.go","lineNumber":171,"sourceCode":"// SearchWithResult 执行搜索并返回包含IsFinal标记的结果\nfunc (p *DyyjPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {\n\treturn p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)\n}\n\n// searchImpl 搜索实现\nfunc (p *DyyjPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tif p.debugMode {\n\t\tlog.Printf(\"[DYYJ] 开始搜索: %s\", keyword)\n\t}\n\n\t// 第一步：执行搜索获取结果列表\n\t// 使用优化的客户端（连接池）而不是传入的client\n\tsearchResults, err := p.executeSearch(p.optimizedClient, keyword)\n\tif err != nil {\n\t\tif p.debugMode {\n\t\t\tlog.Printf(\"[DYYJ] 执行搜索失败: %v\", err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"[%s] 执行搜索失败: %w\", p.Name(), err)\n\t}\n\n\tif p.debugMode {\n\t\tlog.Printf(\"[DYYJ] 搜索获取到 %d 个结果\", len(searchResults))\n\t}\n\t// The Flarum API response already includes each relevant post's content and\n\t// extracted links. Do not fall back to HTML detail pages, which are protected\n\t// by a Cloudflare challenge.\n\tif hasInlineLinks(searchResults) {\n\t\treturn plugin.FilterResultsByKeyword(searchResults, keyword), nil\n\t}\n\n\t// 第二步：先对标题进行关键词过滤，只处理包含关键词的结果（避免不必要的详情页请求）\n\ttitleFilteredResults := p.filterByTitleKeyword(searchResults, keyword)\n\tif p.debugMode {\n\t\tlog.Printf(\"[DYYJ] 标题关键词过滤后剩余 %d 个结果（将只对这些结果获取详情页）\", len(titleFilteredResults))\n\t}\n","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/dyyj/dyyj.go#L153-L189","documentation":"Generic wrapper in dyyj.searchImpl for any failure returned by p.executeSearch (which itself may use HTML scraping or the Flarum JSON API). The inner error is preserved via %w, so this is a contextual wrapper, not a distinct failure. It indicates the whole search pipeline for this plugin failed.","triggerScenarios":"Any underlying cause inside executeSearch: request construction failure, network error after retries, non-200 status, HTML/JSON parse failure, or empty results path that returns an error.","commonSituations":"Site blocked the client (cloudflare challenge); API endpoint changed; keyword triggers server-side rate limiting; network/proxy outage in the deployment environment.","solutions":["Inspect the wrapped cause with errors.Unwrap / %v of the returned error — fix the root cause first","Run with debugMode=true to get the pre-wrap log line identifying the failing stage","Verify network access to BaseURL from the host (curl the search URL)","Check whether the site/API changed and update selectors or API params","Ensure doRequestWithRetry backoff is adequate for a rate-limited site"],"exampleFix":"// before\nresults, err := plugin.Search(ctx, keyword)\nif err != nil {\n\tlog.Fatal(err)\n}\n// after\nresults, err := plugin.Search(ctx, keyword)\nif err != nil {\n\tvar rootErr error\n\tfor e := err; e != nil; e = errors.Unwrap(e) {\n\t\trootErr = e\n\t}\n\tlog.Fatalf(\"search failed: %v (root cause: %v)\", err, rootErr)\n}","handlingStrategy":"try-catch","validationCode":"url, err := url.Parse(pluginBaseURL); if err != nil || url.Host == \"\" { return errors.New(\"plugin base URL invalid\") }","typeGuard":null,"tryCatchPattern":"results, err := p.searchImpl(ctx, keyword)\nif err != nil {\n\tlog.Printf(\"[%s] search failed: %v\", p.Name(), err) // %v shows the full wrap chain\n\treturn nil, err\n}","preventionTips":["Always unwrap to the root cause before troubleshooting","Enable debugMode in development to see the failing stage's own log line","Monitor wrapped error chains with errors.Is/As rather than string matching","Keep per-stage errors distinct so the wrapper stays diagnosable"],"tags":["go","scraper","error-wrapping","network"],"backgroundTag":"api-request-failed","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"}