fish2018/pansou · error
获取测试凭证失败
Error message
获取测试凭证失败: %w
What it means
After the credential_action_id was validated, discoverActionIDs tried to mint test credentials via p.getCredentials("test", credentialActionID, p.client) and that call returned an error. Discovery cannot proceed to verify the intermediate/final link IDs without valid test credentials.
Solutions
- Re-run discovery (retry) — transient/rate-limit failures usually clear after backoff.
- Add delay/backoff between candidate verification probes to avoid tripping rate limits.
- Check the wrapped getCredentials error via DebugLog to see HTTP status vs parse failure.
- Verify the site is reachable and the plugin version matches the current upstream API.
Defensive patterns
Strategy: retry
Try / catch
ids, err := plugin.DiscoverActionIDs()
if err != nil && strings.Contains(err.Error(), "获取测试凭证失败") {
time.Sleep(rateLimitBackoff)
ids, err = plugin.DiscoverActionIDs()
} Prevention
- Throttle discovery probes to avoid rate limits
- Retry with exponential backoff
- Check HTTP status of credential endpoint during incidents
- Keep plugin updated for API changes
When it happens
Trigger: Running discoverActionIDs when the credential endpoint rejects the (just-validated) credential_action_id at test time — e.g. the ID validated once but the endpoint then returns non-200, malformed JSON, or a rate-limit response for the "test" keyword request.
Common situations: Rate limiting after many candidate probes during discovery; transient 5xx; the site accepting a probe but blocking rapid subsequent requests; upstream API change between validation and credential minting.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/be508d03273151c9.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panyq/panyq.go:484
wg.Wait()
close(credIDChan)
// 从通道中获取第一个有效ID
var credentialIDFound bool
for id := range credIDChan {
finalIDs[ActionIDKeys[0]] = id
credentialIDFound = true
break
}
if !credentialIDFound {
return nil, fmt.Errorf("未能验证credential_action_id")
}
// 获取测试凭证用于后续验证
testCreds, err := p.getCredentials("test", finalIDs[ActionIDKeys[0]], p.client)
if err != nil {
return nil, fmt.Errorf("获取测试凭证失败: %w", err)
}
if DebugLog {
fmt.Printf("panyq: 获取到测试凭证: sign=%.10s..., hash=%.10s..., sha=%.10s...\n",
testCreds.Sign, testCreds.Hash, testCreds.Sha)
}
// 从剩余ID中排除已使用的ID
remainingIDs := make([]string, 0, len(potentialIDs)-1)
for _, id := range potentialIDs {
if id != finalIDs[ActionIDKeys[0]] {
remainingIDs = append(remainingIDs, id)
}
}
// 2. 验证intermediate_action_id - 从后向前验证
if DebugLog {
fmt.Printf("panyq: validating intermediate_action_id (%d candidates)...\n", len(remainingIDs))View on GitHub (pinned to beaa561337)