{"record":{"id":"6680f4b4a52209c3","repo":"vitessio/vitess","slug":"protojson-error-v","errorCode":null,"errorMessage":"protojson error: %v","messagePattern":"protojson error: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/vtctl.go","lineNumber":3978,"sourceCode":"//\n//\tupdated and mixed types will use jsonpb as well.\nfunc MarshalJSON(obj any) (data []byte, err error) {\n\tswitch obj := obj.(type) {\n\tcase proto.Message:\n\t\t// Note: We also end up in this case if \"obj\" is NOT a proto.Message but\n\t\t// has an anonymous (embedded) field of the type \"proto.Message\".\n\t\t// In that case jsonpb may panic if the \"obj\" has non-exported fields.\n\n\t\t// Marshal the protobuf message.\n\t\tdata, err = protojson.MarshalOptions{\n\t\t\tMultiline:       true,\n\t\t\tIndent:          \"  \",\n\t\t\tUseProtoNames:   true,\n\t\t\tUseEnumNumbers:  true,\n\t\t\tEmitUnpopulated: true,\n\t\t}.Marshal(obj)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"protojson error: %v\", err)\n\t\t}\n\tcase []string:\n\t\tif len(obj) == 0 {\n\t\t\treturn []byte{'[', ']'}, nil\n\t\t}\n\t\tdata, err = json.MarshalIndent(obj, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"json error: %v\", err)\n\t\t}\n\tdefault:\n\t\tdata, err = json.MarshalIndent(obj, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"json error: %v\", err)\n\t\t}\n\t}\n\n\treturn data, nil\n}","sourceCodeStart":3960,"sourceCodeEnd":3996,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/vtctl.go#L3960-L3996","documentation":"MarshalJSON's proto branch uses protojson.MarshalOptions to encode protobuf objects; a protojson failure (invalid proto message, wrong concrete type, or unsupported field) is wrapped as 'protojson error'. Unlike encoding/json, protojson can fail on invalid proto3 messages.","triggerScenarios":"A vtctl command printing a protobuf value via MarshalJSON where protojson.Marshal rejects the object (e.g. nil proto message contents or a type not registered).","commonSituations":"Passing a non-proto value into the protobuf branch by mistake; corrupted protobuf data from topo; version mismatch between generated pb code and protojson library.","solutions":["Check the wrapped %v error for the specific protojson failure reason","Verify the object being marshaled is a valid, populated protobuf message","Ensure generated proto code and google.golang.org/protobuf versions are in sync (go mod tidy/upgrade)"],"exampleFix":"// before\nreturn nil, fmt.Errorf(\"protojson error: %v\", err)\n// after\nreturn nil, vterrors.Wrapf(err, vtrpcpb.Code_INTERNAL, \"protojson error marshaling %T\", obj)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"data, err := MarshalJSON(val)\nif err != nil {\n\tif strings.Contains(err.Error(), \"protojson error\") {\n\t\tlog.Warnf(\"protojson failed for %T, using fallback encoder\", val)\n\t\treturn json.Marshal(val)\n\t}\n\treturn err\n}","preventionTips":["Keep generated proto code and google.golang.org/protobuf versions aligned","Validate protobuf messages before marshaling (protojson rejects invalid proto3 data)","Add unit tests covering MarshalJSON for every protobuf type printed by vtctl"],"tags":["vtctl","protojson","serialization","go"],"backgroundTag":"protojson-marshal-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}