flipped-aurora/gin-vue-admin · error

序列化结果失败: %v

Error message

序列化结果失败: %v

What it means

At the end of gva_execute's Handle (server/mcp/gva_execute.go:278), the ExecuteResponse is serialized with json.MarshalIndent for return to the MCP client. Marshal failure here is theoretically near-impossible — the struct contains only strings, bools, uints, maps and slices — but if it happens the successful execution result cannot be delivered and this error is returned instead.

Source

Thrown at server/mcp/gva_execute.go:278

		reviewMessage = fmt.Sprintf("\n\n📁 已生成以下文件:\n%s\n\n💡 提示:可以检查生成的代码是否满足原始需求。", strings.Join(pathsInfo, "\n"))
	} else if originalRequirement == "" {
		reviewMessage = "\n\n💡 提示:如需代码复检,请提供原始需求描述。"
	}

	// 序列化响应
	response := ExecuteResponse{
		Success:        result.Success,
		Message:        result.Message,
		PackageID:      result.PackageID,
		HistoryID:      result.HistoryID,
		Paths:          result.Paths,
		GeneratedPaths: result.GeneratedPaths,
		NextActions:    result.NextActions,
	}

	responseJSON, err := json.MarshalIndent(response, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("序列化结果失败: %v", err)
	}

	return &mcp.CallToolResult{
		Content: []mcp.Content{
			mcp.NewTextContent(fmt.Sprintf("执行结果:\n\n%s%s", string(responseJSON), reviewMessage)),
		},
	}, nil
}

// validateExecutionPlan 验证执行计划的完整性
func (g *GVAExecutor) validateExecutionPlan(ctx context.Context, plan *ExecutionPlan) error {
	if plan.PackageName == "" {
		return errors.New("packageName 不能为空")
	}
	if plan.PackageType != "package" && plan.PackageType != "plugin" {
		return errors.New("packageType 必须是 'package' 或 'plugin'")
	}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Read the %v suffix to identify the unsupported type json reports.
  2. Inspect recent changes to ExecuteResponse or the response construction in Handle for non-JSON-serializable fields.
  3. Remove or convert the offending field (e.g. fmt.Sprintf it to a string) before marshaling.
  4. As a stopgap, log result fields individually so execution results aren't lost while the marshal bug is fixed.

Example fix

// before: adding a non-serializable field
type ExecuteResponse struct {
	Cleanup func() `json:"-"` // if ever tagged into JSON flow
}
// after: keep only serializable fields
nextActions := fmt.Sprintf("%v", result.NextActions)
response := ExecuteResponse{Success: result.Success, Message: result.Message, GeneratedPaths: result.GeneratedPaths}
Defensive patterns

Strategy: try-catch

Type guard

func isJSONSerializable(v any) bool {
	_, err := json.Marshal(v)
	return err == nil
}

Try / catch

responseJSON, err := json.MarshalIndent(response, "", "  ")
if err != nil {
	// fall back to a minimal result so execution success isn't swallowed
	return mcp.NewToolResultText(fmt.Sprintf("执行结果:%v", result.Message)), nil
}

Prevention

When it happens

Trigger: json.MarshalIndent failing on the ExecuteResponse — realistically only if the struct gains a non-serializable field (func, channel, cyclic map) or a map key type JSON cannot encode in a future code change.

Common situations: Almost exclusively encountered after code modifications to ExecuteResponse or the result-mapping block; custom forks adding channels/funcs or map[func]string fields; not triggered by caller input at all.

Related errors


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