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
- Surface result.Msg to the caller — it describes the exact business rule violated
- Verify the parameters/IDs the MCP tool forwarded are still valid in the GVA system
- Check the target endpoint's service code for the specific msg string to find the failing rule
- 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
- Validate IDs/parameters against the live GVA data before calling
- Keep the MCP user's roles/Casbin policies aligned with required operations
- Map known upstream Msg strings to friendly client messages
- Log code+msg pairs to track recurring business-rule rejections
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.