flipped-aurora/gin-vue-admin · error
解析响应失败: %w
Error message
解析响应失败: %w
What it means
The upstream returned HTTP 200 but its JSON body could not be unmarshaled into upstreamEnvelope[T]; the error is wrapped as '解析响应失败'. This means the response is not the expected {code,msg,data} envelope shape (or data does not match T).
Source
Thrown at server/mcp/http_client.go:134
req.Header.Set("Accept", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("请求上游接口失败: %w", err)
}
defer resp.Body.Close()
rawBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
if resp.StatusCode >= http.StatusBadRequest {
return nil, fmt.Errorf("上游接口返回状态码 %d: %s", resp.StatusCode, string(rawBody))
}
var result upstreamEnvelope[T]
if err := json.Unmarshal(rawBody, &result); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
}
if result.Code != 0 {
return nil, fmt.Errorf("上游接口业务错误: %s", result.Msg)
}
return &result, nil
}
func getUpstream[T any](ctx context.Context, endpoint string, query url.Values) (*upstreamEnvelope[T], error) {
return doUpstream[T](ctx, http.MethodGet, endpoint, query, nil)
}
func postUpstream[T any](ctx context.Context, endpoint string, body any) (*upstreamEnvelope[T], error) {
return doUpstream[T](ctx, http.MethodPost, endpoint, nil, body)
}
func deleteUpstream[T any](ctx context.Context, endpoint string, body any) (*upstreamEnvelope[T], error) {
return doUpstream[T](ctx, http.MethodDelete, endpoint, nil, body)
}View on GitHub (pinned to 3136500ef3)
Solutions
- Log/inspect string(rawBody) to see what the upstream actually returned
- Verify the generic type parameter T matches the endpoint's response data model
- Check whether a proxy or auth middleware is returning HTML instead of JSON
- Align T with the current server response struct after any API change
Example fix
// before
type upstreamEnvelope[T any] struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data T `json:"data"`
}
// after (tolerate data being absent)
var result upstreamEnvelope[T]
if len(bytes.TrimSpace(rawBody)) == 0 {
return nil, fmt.Errorf("解析响应失败: 空响应体")
}
if err := json.Unmarshal(rawBody, &result); err != nil {
return nil, fmt.Errorf("解析响应失败: %w", err)
} Defensive patterns
Strategy: type-guard
Validate before calling
// sniff the response shape before trusting it
if !strings.HasPrefix(strings.TrimSpace(string(rawBody)), "{") {
// not JSON — likely an HTML proxy/login page; fix base URL or auth Type guard
func isValidEnvelope[T any](raw []byte) (*upstreamEnvelope[T], bool) {
var probe struct {
Code *int `json:"code"`
}
if err := json.Unmarshal(raw, &probe); err != nil || probe.Code == nil {
return nil, false
}
var env upstreamEnvelope[T]
if err := json.Unmarshal(raw, &env); err != nil {
return nil, false
}
return &env, true
} Try / catch
data, err := fetchPublicUpstream[Item](ctx, endpoint)
if err != nil {
if strings.Contains(err.Error(), "解析响应失败") {
// log raw body upstream of here; treat as upstream contract violation
}
return err
} Prevention
- Keep generic type T aligned with the endpoint's data model after API changes
- Add a contract test per endpoint asserting unmarshal succeeds
- Ensure no proxy sits between MCP and GVA serving HTML pages
- Return an explicit error on empty response bodies
When it happens
Trigger: Upstream returns HTML (login page/proxy error page) with 200; upstream response shape changed; generic type T does not match the actual data field type (e.g. expecting array but getting object); empty body with 200.
Common situations: Reverse proxy intercepting requests and serving an HTML error/login page; a GVA endpoint updated its response model; wrong generic type parameter passed to fetchPublicUpstream; gzip/charset issues served by a misconfigured proxy.
Related errors
- LLM request failed
- 参数错误:generatedFiles 必须是JSON字符串
- params 必须是合法 JSON
- httpHeader 必须是 {"Key":"Value"} 形式的 JSON 对象
- fatal error unmarshal config: %w
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/03b4f8b5346f6a1f.
Report an issue: GitHub.