flipped-aurora/gin-vue-admin · error

序列化上游请求失败: %w

Error message

序列化上游请求失败: %w

What it means

When body != nil, doUpstream serializes it with json.Marshal; failure is wrapped as '序列化上游请求失败'. json.Marshal only fails on unsupported types (channels, funcs, cyclic structures, invalid numbers), so this almost always signals a bug in the request payload type.

Source

Thrown at server/mcp/http_client.go:181

	}
	if !strings.HasPrefix(endpoint, "/") {
		endpoint = "/" + endpoint
	}

	baseURL := upstreamBaseURL()
	requestURL, err := url.Parse(baseURL + endpoint)
	if err != nil {
		return nil, fmt.Errorf("构建上游请求地址失败: %w", err)
	}
	if len(query) > 0 {
		requestURL.RawQuery = query.Encode()
	}

	var reader io.Reader
	if body != nil {
		payload, err := json.Marshal(body)
		if err != nil {
			return nil, fmt.Errorf("序列化上游请求失败: %w", err)
		}
		reader = bytes.NewReader(payload)
	}

	timeoutCtx, cancel := context.WithTimeout(ctx, requestTimeout())
	defer cancel()

	req, err := http.NewRequestWithContext(timeoutCtx, method, requestURL.String(), reader)
	if err != nil {
		return nil, fmt.Errorf("创建上游请求失败: %w", err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set(upstreamAuthHeader, token)
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	// 链路传播:外部 AI → MCP 进程 → GVA 主服务串成同一条 trace
	logger.InjectTraceHeaders(timeoutCtx, req)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Look at the wrapped error — json.Marshal names the offending field/type
  2. Remove or replace unsupported field types (channel, func, cyclic refs) in the request struct
  3. Test the payload type with json.Marshal in a unit test
  4. If NaN/Inf floats are possible, sanitize them before passing body

Example fix

// before
body := map[string]any{"cb": make(chan int)}
resp, err := postUpstream[Result](ctx, "/api/x", nil, body)
// after
body := map[string]any{"id": 123}
resp, err := postUpstream[Result](ctx, "/api/x", nil, body)
Defensive patterns

Strategy: validation

Validate before calling

func marshalable(v any) error {
	_, err := json.Marshal(v)
	return err
}

Try / catch

result, err := postUpstream[Data](ctx, "/api/x", nil, body)
if err != nil {
	var marshalErr *json.UnsupportedTypeError
	if errors.As(err, &marshalErr) || strings.Contains(err.Error(), "序列化上游请求失败") {
		// inspect body struct for unsupported field types
	}
	return err
}

Prevention

When it happens

Trigger: Request struct contains a channel/func field; cyclic pointer structure; custom MarshalJSON that returns an error; NaN/Inf float values.

Common situations: Passing a context-bearing or cyclic object as body; a recently added field of unsupported type; hand-written MarshalJSON with a bug.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/ab9dd4067c27d3b3. Report an issue: GitHub.