fish2018/pansou · error

[ ] 解析接口配置失败

Error message

[%s] 解析接口配置失败: %w

What it means

The bootstrap config payload from GET /test was received and XOR-decoded with bootstrapKey, but the decoded string is not valid JSON (or is not a JSON string decodable by jsonutil.UnmarshalString), so fetchConfig cannot unmarshal it into apiConfig. This indicates the encrypted/encoded payload did not decode as expected.

Solutions

  1. Inspect the raw response.Data and the decoded string to confirm what the server actually returned
  2. Verify bootstrapKey and the xorUTF16 scheme match the current server-side encoding
  3. Confirm the server's /test endpoint still returns the XOR-encoded JSON config; update decoding if the contract changed
  4. Check for proxies/CDNs rewriting the response body

Example fix

// before
decoded := xorUTF16(response.Data, bootstrapKey) // stale key
c := xorUTF16Decode(data, currentBootstrapKey) // after: use the key matching the deployed API
Defensive patterns

Strategy: try-catch

Validate before calling

if resp.Code == http.StatusOK && resp.Data == "" {
    return errors.New("empty bootstrap payload; decoding will fail")
}

Type guard

func looksLikeConfig(decoded string) bool {
    var probe map[string]json.RawMessage
    return json.Unmarshal([]byte(decoded), &probe) == nil && len(probe) > 0
}

Try / catch

cfg, err := p.fetchConfig(ctx, client)
if err != nil {
    if strings.Contains(err.Error(), "解析接口配置失败") {
        log.Printf("bootstrap payload failed to decode; check key/encoding drift: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: jsonutil.UnmarshalString(xorUTF16(response.Data, bootstrapKey), &config) returns an error during fetchConfig, typically because the XOR-decoded data is garbled or truncated.

Common situations: The bootstrapKey or xorUTF16 encoding no longer matches what the server sends after an API-side change; the server returned a non-config payload (e.g., HTML error body) that still passed the code==200 check; a proxy mangled the response body.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/9f281d1b12014955. Report an issue: GitHub.

Appendix: source

Thrown at plugin/yingso/yingso.go:202

		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{
		PageSize: pageSize,
		PageNum:  1,
		Title:    keyword,
		Root:     0,
		Category: "all",
		UserID:   config.UserID,
	}
	encrypted, err := encryptPayload(payload, config)
	if err != nil {

View on GitHub (pinned to beaa561337)