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

  1. Re-run discovery (retry) — transient/rate-limit failures usually clear after backoff.
  2. Add delay/backoff between candidate verification probes to avoid tripping rate limits.
  3. Check the wrapped getCredentials error via DebugLog to see HTTP status vs parse failure.
  4. 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

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)