fish2018/pansou · error
[ ] 获取接口配置失败
Error message
[%s] 获取接口配置失败: %w
What it means
fetchConfig calls GET {apiBaseURL}/test via requestJSON to obtain the API configuration envelope; if that request fails at the transport/decoding level, the error is wrapped as 获取接口配置失败. This is a bootstrap step — search cannot proceed without the config (e.g. a key extracted from the XOR-decoded Data).
Solutions
- Verify apiBaseURL is correct and reachable (curl {apiBaseURL}/test).
- Inspect the wrapped error from requestJSON for connection vs decode details.
- Update the plugin/config if the upstream endpoint changed.
- Add a timeout and retry for transient network failures.
Example fix
// before
if err := p.requestJSON(ctx, client, http.MethodGet, p.apiBaseURL+"/test", nil, &response); err != nil {
return apiConfig{}, fmt.Errorf("[%s] 获取接口配置失败: %w", p.Name(), err)
}
// after
endpoint := strings.TrimRight(p.apiBaseURL, "/") + "/test"
if err := p.requestJSON(ctx, client, http.MethodGet, endpoint, nil, &response); err != nil {
return apiConfig{}, fmt.Errorf("[%s] 获取接口配置失败: %w (endpoint: %s)", p.Name(), err, endpoint)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: validate config before calling
if p.apiBaseURL == "" {
return fmt.Errorf("apiBaseURL is not configured")
}
u, err := url.Parse(p.apiBaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid apiBaseURL: %q", p.apiBaseURL)
} Try / catch
cfg, err := fetchConfig(ctx, client)
if err != nil {
if strings.Contains(err.Error(), "获取接口配置失败") {
log.Printf("Yingso config endpoint unreachable, retrying: %v", err)
return fetchConfigWithRetry(ctx, client, 3)
}
return err
} Prevention
- Verify apiBaseURL with curl after every config change.
- Set explicit HTTP timeouts on the client.
- Retry the bootstrap /test call a few times on startup.
- Alert on repeated config-fetch failures rather than silently failing searches.
When it happens
Trigger: The GET to p.apiBaseURL+"/test" failed: connection refused/timeout, non-2xx status, or the response body could not be decoded into apiEnvelope[string] by requestJSON.
Common situations: Wrong or outdated apiBaseURL in the plugin config; upstream /test endpoint moved or was removed; firewall/proxy blocks the request; upstream serving an HTML error page instead of the expected envelope.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/7b5194041bd1d181.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yingso/yingso.go:193
for index, result := range resolved {
if !valid[index] || len(result.Links) == 0 {
continue
}
linkKey := result.Links[0].URL + "\x00" + result.Links[0].Password
if _, exists := seen[linkKey]; exists {
continue
}
seen[linkKey] = struct{}{}
results = append(results, result)
}
return plugin.FilterResultsByKeyword(results, keyword), nil
}
func (p *YingsoPlugin) fetchConfig(ctx context.Context, client *http.Client) (apiConfig, error) {
var response apiEnvelope[string]
if err := p.requestJSON(ctx, client, http.MethodGet, p.apiBaseURL+"/test", nil, &response); err != nil {
return apiConfig{}, fmt.Errorf("[%s] 获取接口配置失败: %w", p.Name(), err)
}
if response.Code != http.StatusOK || response.Data == "" {
return apiConfig{}, fmt.Errorf("[%s] 接口配置异常: code=%d msg=%s", p.Name(), response.Code, response.Msg)
}
decoded := xorUTF16(response.Data, bootstrapKey)
var config apiConfig
if err := jsonutil.UnmarshalString(decoded, &config); err != nil {
return apiConfig{}, fmt.Errorf("[%s] 解析接口配置失败: %w", p.Name(), err)
}
if config.URLVersion == "" || config.UserID == "" || config.Start < 0 || config.End <= config.Start || config.End > 24 {
return apiConfig{}, fmt.Errorf("[%s] 接口配置缺少必要字段", p.Name())
}
return config, nil
}
func (p *YingsoPlugin) search(ctx context.Context, client *http.Client, config apiConfig, keyword string) ([]searchItem, error) {
payload := searchPayload{View on GitHub (pinned to beaa561337)