flipped-aurora/gin-vue-admin · error

上游接口业务错误: %s

Error message

上游接口业务错误: %s

What it means

The upstream returned a valid envelope but result.Code != 0, i.e. the GVA main service reported a business-level failure; the message includes the upstream's Msg text. This is the application-layer error contract of gin-vue-admin responses ({code:0} means success).

Source

Thrown at server/mcp/http_client.go:137

	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)
}

func doUpstream[T any](ctx context.Context, method, endpoint string, query url.Values, body any) (*upstreamEnvelope[T], error) {
	token := authTokenFromContext(ctx)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Surface result.Msg to the caller — it describes the exact business rule violated
  2. Verify the parameters/IDs the MCP tool forwarded are still valid in the GVA system
  3. Check the target endpoint's service code for the specific msg string to find the failing rule
  4. If msg indicates permission, adjust the user's role/Casbin policy in GVA admin
Defensive patterns

Strategy: type-guard

Type guard

func isBusinessError(err error) (msg string, ok bool) {
	const prefix = "上游接口业务错误: "
	if strings.HasPrefix(err.Error(), prefix) {
		return strings.TrimPrefix(err.Error(), prefix), true
	}
	return "", false
}

Try / catch

result, err := postUpstream[Item](ctx, "/api/item/create", nil, payload)
if err != nil {
	if msg, ok := isBusinessError(err); ok {
		// show result.Msg semantics to the end user
		return fmt.Errorf("operation rejected: %s", msg)
	}
	return err
}

Prevention

When it happens

Trigger: Business rule rejection by the target GVA endpoint: record not found, duplicate key, permission denied at service layer, invalid parameters the handler accepted but service rejected.

Common situations: MCP tool calling an endpoint with an ID that no longer exists; user role lacks permission for the operation; validation like unique-username violated; upstream service returning msg in Chinese describing the exact rule.

Related errors


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