{"record":{"id":"7e4cdef8fbe31e7e","repo":"fish2018/pansou","slug":"w-7e4cde","errorCode":null,"errorMessage":"获取搜索凭证失败: %w","messagePattern":"获取搜索凭证失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panyq/panyq.go","lineNumber":223,"sourceCode":"\tactionIDs, err := p.getOrDiscoverActionIDs()\n\tif err != nil {\n\t\t// fmt.Println(\"panyq: failed to get Action IDs:\", err)\n\t\treturn nil, fmt.Errorf(\"获取Action ID失败: %w\", err)\n\t}\n\n\t// 步骤1: 获取搜索凭证\n\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 {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panyq/panyq.go#L205-L241","documentation":"doSearch fails while obtaining search credentials after refreshing the Action ID: the wrapped error comes from p.getCredentials(keyword, actionID, client), which performs the site's credential API call. This means the plugin could not obtain a valid Sign/Hash/Sha credential even after one Action ID refresh retry. It aborts the search before any results are fetched.","triggerScenarios":"Calling doSearch (or the plugin search entry) when the credential endpoint returns an error — e.g. the site changed its credential API, the Action ID is stale/wrong, the upstream returns non-200, or the response JSON cannot be parsed.","commonSituations":"Upstream site updated its frontend/obfuscation so action IDs no longer match; network/firewall blocking the site; temporary 5xx from the target site; rate limiting.","solutions":["Re-run the search to trigger Action ID re-discovery (cached IDs may be stale — clear the in-memory action ID cache or restart the plugin).","Check DebugLog output to see the underlying wrapped error from getCredentials and confirm which HTTP status/parse failure occurred.","Verify network connectivity to BaseURL from the host (curl the site homepage).","Update the plugin to a version matching the current upstream site layout."],"exampleFix":"// before\ncredentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)\nif err != nil {\n    return nil, fmt.Errorf(\"获取搜索凭证失败: %w\", err)\n}\n// after\ncredentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)\nif err != nil {\n    p.invalidateActionIDCache() // drop possibly stale IDs before returning\n    return nil, fmt.Errorf(\"获取搜索凭证失败: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"if err := pingBaseURL(BaseURL); err != nil {\n    return fmt.Errorf(\"site unreachable, skipping panyq search: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"results, err := plugin.Search(keyword)\nif err != nil {\n    if strings.Contains(err.Error(), \"获取搜索凭证失败\") {\n        log.Printf(\"credential fetch failed (site may have changed): %v\", err)\n        return fallbackResults(keyword) // use another source\n    }\n    return err\n}","preventionTips":["Keep the plugin updated against upstream site changes","Check site reachability before search","Clear/rebuild the action ID cache after upstream deploys","Log the wrapped cause (%w) for diagnosis"],"tags":["network","http","upstream","plugin"],"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"}