{"record":{"id":"34953e8d9e80049f","repo":"fish2018/pansou","slug":"w-34953e","errorCode":null,"errorMessage":"获取搜索结果失败: %w","messagePattern":"获取搜索结果失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panyq/panyq.go","lineNumber":230,"sourceCode":"\tcredentials, err := p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)\n\tif err != nil {\n\t\t// 如果获取凭证失败，尝试刷新Action ID并重试\n\t\tactionIDs, err = p.discoverActionIDs()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"刷新Action ID失败: %w\", err)\n\t\t}\n\t\t\n\t\t// 使用新的Action ID重试获取凭证\n\t\tcredentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"获取搜索凭证失败: %w\", err)\n\t\t}\n\t}\n\n\t// 步骤2: 获取第一页搜索结果列表\n\thits, maxPageNum, err := p.getSearchResults(credentials.Sign, 1, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"获取搜索结果失败: %w\", err)\n\t}\n\n\tif len(hits) == 0 {\n\t\tif DebugLog {\n\t\t\tfmt.Println(\"panyq: no results found for\", keyword)\n\t\t}\n\t\treturn []model.SearchResult{}, nil\n\t}\n\t\n\t// 如果有多页结果，并发获取其他页的数据\n\tif maxPageNum > 1 {\n\t\tif DebugLog {\n\t\t\tfmt.Printf(\"panyq: found %d pages, fetching additional pages...\\n\", maxPageNum)\n\t\t}\n\t\tif maxPageNum >= 3 {\n\t\t\tmaxPageNum = 3\n\t\t}\n\t\t// 创建通道存储其他页的结果","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panyq/panyq.go#L212-L248","documentation":"doSearch fails at step 2: p.getSearchResults(credentials.Sign, 1, client) returned an error while fetching the first page of search results. The Sign credential was obtained, but the search API call itself failed (HTTP error or unparseable response).","triggerScenarios":"Calling doSearch when the search endpoint rejects the Sign (expired/invalid credential), returns non-200, or returns malformed JSON that getSearchResults cannot decode.","commonSituations":"Credential expired between fetching and searching; upstream API changed response format; transient network failure or 5xx; IP blocked/rate limited by the site.","solutions":["Retry the search — transient failures and expired signs typically resolve on a fresh credential fetch.","Inspect the wrapped error from getSearchResults (status code vs parse error) with DebugLog enabled.","Verify the site is reachable and the response format matches what the plugin expects.","Update the plugin if the upstream API changed."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if !isSiteReachable(BaseURL) {\n    return errors.New(\"panyq upstream unreachable, skip search\")\n}","typeGuard":null,"tryCatchPattern":"hits, err := plugin.Search(keyword)\nif err != nil && strings.Contains(err.Error(), \"获取搜索结果失败\") {\n    time.Sleep(backoff)\n    hits, err = plugin.Search(keyword) // fresh sign on retry\n}","preventionTips":["Retry once with backoff — signs can expire between fetch and search","Monitor upstream API format changes","Avoid hammering the site to prevent IP blocks","Log wrapped cause for status vs parse distinction"],"tags":["network","http","search","upstream"],"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"}