{"record":{"id":"226197ad32d12e64","repo":"fish2018/pansou","slug":"action-id-w","errorCode":null,"errorMessage":"获取Action ID失败: %w","messagePattern":"获取Action ID失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panyq/panyq.go","lineNumber":208,"sourceCode":"\treturn results, err\n}\n\n// SearchWithResult 执行搜索并返回包含IsFinal标记的结果\nfunc (p *PanyqPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {\n\treturn p.AsyncSearchWithResult(keyword, p.doSearch, p.MainCacheKey, ext)\n}\n\n// doSearch 实际的搜索实现\nfunc (p *PanyqPlugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {\n\tif DebugLog {\n\t\tfmt.Println(\"panyq: searching for\", keyword)\n\t}\n\n\t// 尝试获取或发现 Action ID\n\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","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panyq/panyq.go#L190-L226","documentation":"doSearch first obtains the site's Action IDs (obfuscated parameter identifiers scraped/discovered from the upstream API page) via getOrDiscoverActionIDs. If neither the cached nor a fresh discovery succeeds, it wraps the underlying error as \"获取Action ID失败\" — the plugin cannot construct valid search requests without these IDs.","triggerScenarios":"getOrDiscoverActionIDs returns an error: cached IDs absent and discoverActionIDs fails because the upstream page is unreachable, its HTML structure changed so the regex/parser no longer matches, or the request was blocked (403/captcha).","commonSituations":"Upstream site updated its frontend so Action ID extraction breaks; network/anti-bot blocking the discovery request; first-run with empty cache during an outage; version drift where the site rotates IDs.","solutions":["Inspect the wrapped error to see whether it was a network failure or a parse failure.","Check whether the upstream page structure changed and update the discovery regex/parser.","Clear any stale cache so discovery is retried cleanly.","Add retry with backoff for transient discovery failures.","Verify reachability of the discovery endpoint (curl it and compare against the parser expectations)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Go (caller): health-check the plugin's upstream before searching\nids, err := plugin.GetOrDiscoverActionIDs() // if exported; otherwise probe the site URL\nif err != nil {\n    return nil, fmt.Errorf(\"panyq upstream unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"result, err := plugin.Search(keyword, ext)\nif err != nil && strings.Contains(err.Error(), \"获取Action ID失败\") {\n    // upstream structure changed or discovery request failed; retry later or alert\n    log.Printf(\"panyq action-id discovery failed: %v\", err)\n    return err\n}","preventionTips":["Monitor the upstream page structure; alert when discovery parsing stops matching.","Retry with exponential backoff for transient discovery failures.","Keep the plugin updated when the upstream site ships frontend changes.","Cache discovered IDs with a sensible TTL rather than relying on one-shot discovery."],"tags":["scraping","api","go","upstream"],"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"}