vitessio/vitess · error
json error: %v
Error message
json error: %v
What it means
vtctl's JSON output helper wraps any failure of json.MarshalIndent when serializing a command's result object. The error means Go's encoding/json could not serialize the value (e.g. an unsupported type such as a channel, func, or complex number, or a cyclic structure). It is thrown so the caller returns a descriptive error instead of an unusable nil data blob.
Source
Thrown at go/vt/vtctl/vtctl.go:3986
// Marshal the protobuf message.
data, err = protojson.MarshalOptions{
Multiline: true,
Indent: " ",
UseProtoNames: true,
UseEnumNumbers: true,
EmitUnpopulated: true,
}.Marshal(obj)
if err != nil {
return nil, fmt.Errorf("protojson error: %v", err)
}
case []string:
if len(obj) == 0 {
return []byte{'[', ']'}, nil
}
data, err = json.MarshalIndent(obj, "", " ")
if err != nil {
return nil, fmt.Errorf("json error: %v", err)
}
default:
data, err = json.MarshalIndent(obj, "", " ")
if err != nil {
return nil, fmt.Errorf("json error: %v", err)
}
}
return data, nil
}
// RunCommand will execute the command using the provided wrangler.
// It will return the actionPath to wait on for long remote actions if
// applicable.
func RunCommand(ctx context.Context, wr *wrangler.Wrangler, args []string) error {
if len(args) == 0 {
wr.Logger().Printf("No command specified. Please see the list below:\n\n")
PrintAllCommands(wr.Logger())View on GitHub (pinned to 01a25a7d17)
Solutions
- Inspect the command result struct for fields that json cannot encode (func, chan, complex, cycles) and fix or remove them
- Add a MarshalJSON method to the offending custom type
- If the object should be empty, ensure the []byte path receives a truly empty value so the nil early-return is taken
- Re-run the command; if reproducible, capture the underlying %v detail which names the unsupported JSON value
Example fix
// before
type Result struct { Hook func() }
// after
type Result struct { HookName string } // encodable field instead of func Defensive patterns
Strategy: validation
Validate before calling
if err := json.Marshal(obj); err != nil {
return nil, fmt.Errorf("result object is not JSON-encodable: %v", err)
} Type guard
func isJSONEncodable(v any) bool {
return json.Valid(mustMarshalOrEmpty(v))
} Try / catch
data, err := jsonOutput(obj)
if err != nil {
log.Warn("vtctl output marshal failed", slog.Any("error", err))
return err
} Prevention
- Keep vtctl command result structs free of func/chan/complex fields
- Add json.Marshaler implementations for custom output types
- Add unit tests that marshal every command's zero-value result
When it happens
Trigger: Calling a vtctl command whose result object is marshaled in the 'case []byte' branch path: len(obj)==0 returns nil early, otherwise json.MarshalIndent(obj, "", " ") fails on an unencodable value.
Common situations: A command result contains a field of an unsupported type (func, chan, complex) or a reference cycle; custom types without MarshalJSON used in vtctl command output; regressions after changing a result struct.
Related errors
- cannot marshal data: %v
- protojson error: %v
- invalid signature for Trie2: 0x%08x
- range %d should be >= %d
- too big depth for the nested JSON; it exceeds %d
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/adbb0a2c10b716ec.
Report an issue: GitHub.