{"record":{"id":"be508d03273151c9","repo":"fish2018/pansou","slug":"w-be508d","errorCode":null,"errorMessage":"获取测试凭证失败: %w","messagePattern":"获取测试凭证失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/panyq/panyq.go","lineNumber":484,"sourceCode":"\twg.Wait()\n\tclose(credIDChan)\n\t\n\t// 从通道中获取第一个有效ID\n\tvar credentialIDFound bool\n\tfor id := range credIDChan {\n\t\tfinalIDs[ActionIDKeys[0]] = id\n\t\tcredentialIDFound = true\n\t\tbreak\n\t}\n\t\n\tif !credentialIDFound {\n\t\treturn nil, fmt.Errorf(\"未能验证credential_action_id\")\n\t}\n\t\n\t// 获取测试凭证用于后续验证\n\ttestCreds, err := p.getCredentials(\"test\", finalIDs[ActionIDKeys[0]], p.client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"获取测试凭证失败: %w\", err)\n\t}\n\t\n\tif DebugLog {\n\t\tfmt.Printf(\"panyq: 获取到测试凭证: sign=%.10s..., hash=%.10s..., sha=%.10s...\\n\", \n\t\t\ttestCreds.Sign, testCreds.Hash, testCreds.Sha)\n\t}\n\t\n\t// 从剩余ID中排除已使用的ID\n\tremainingIDs := make([]string, 0, len(potentialIDs)-1)\n\tfor _, id := range potentialIDs {\n\t\tif id != finalIDs[ActionIDKeys[0]] {\n\t\t\tremainingIDs = append(remainingIDs, id)\n\t\t}\n\t}\n\t\n\t// 2. 验证intermediate_action_id - 从后向前验证\n\tif DebugLog {\n\t\tfmt.Printf(\"panyq: validating intermediate_action_id (%d candidates)...\\n\", len(remainingIDs))","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/panyq/panyq.go#L466-L502","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"ids, err := plugin.DiscoverActionIDs()\nif err != nil && strings.Contains(err.Error(), \"获取测试凭证失败\") {\n    time.Sleep(rateLimitBackoff)\n    ids, err = plugin.DiscoverActionIDs()\n}","preventionTips":["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"],"tags":["action-id","credentials","upstream","http"],"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"}