{"record":{"id":"ce777168eb859ee7","repo":"go-kratos/kratos","slug":"not-proto-message","errorCode":null,"errorMessage":"not proto message","messagePattern":"not proto message","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"encoding/proto/proto.go","lineNumber":46,"sourceCode":"func (codec) Unmarshal(data []byte, v any) error {\n\tpm, err := getProtoMessage(v)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn proto.Unmarshal(data, pm)\n}\n\nfunc (codec) Name() string {\n\treturn Name\n}\n\nfunc getProtoMessage(v any) (proto.Message, error) {\n\tif msg, ok := v.(proto.Message); ok {\n\t\treturn msg, nil\n\t}\n\tval := reflect.ValueOf(v)\n\tif val.Kind() != reflect.Pointer {\n\t\treturn nil, errors.New(\"not proto message\")\n\t}\n\n\tval = val.Elem()\n\treturn getProtoMessage(val.Interface())\n}\n","sourceCodeStart":28,"sourceCodeEnd":52,"githubUrl":"https://github.com/go-kratos/kratos/blob/668db92c2c001e9552594ba5a8aede8456af6d7e/encoding/proto/proto.go#L28-L52","documentation":"'not proto message' (encoding/proto/proto.go:46) is returned by getProtoMessage during codec.Unmarshal for the 'proto' codec. The helper accepts a proto.Message directly or unwraps any chain of pointers (val.Elem().Interface() recursion), but as soon as it meets a non-pointer that is not a proto.Message it fails. Note the asymmetry: Marshal does a raw type assertion v.(proto.Message) and would panic instead, so this error is specifically the Unmarshal path's graceful rejection.","triggerScenarios":"The proto codec is selected (gRPC, or HTTP with Content-Type whose subtype is 'proto') and Unmarshal is handed a non-proto target: a map[string]any, *struct{}, a value type rather than pointer, a string/[]byte wrapper, or a custom struct from another codebase. Typical with reflect-based generic wrappers that allocate reply types dynamically.","commonSituations":"Server handler bound to a non-proto request/response struct while the route negotiated the proto codec; client declared with proto codec calling an endpoint whose reply is plain JSON-shaped; proxy/middleware that wraps messages in envelope types; protoc version skew producing types registered under google.golang.org/protobuf vs gogo/goprotobuf (the latter does not satisfy the new-gen proto.Message).","solutions":["Pass a pointer to a protoc-generated message (new google.golang.org/protobuf API) as the Unmarshal target, e.g. &pb.HelloReply{}","If the payload is JSON, switch the codec/content-type to json instead of proto","Ensure generated code comes from protoc-gen-go matching the protobuf runtime the codec registers (no gogo/legacy types)","In generic code, type-switch and only route proto.Message targets through this codec"],"exampleFix":"// before\ncodec.Unmarshal(data, &map[string]any{}) // not proto message\n// or handler with non-proto reply under proto content-type\n\n// after\nvar reply pb.HelloReply\nif err := codec.Unmarshal(data, &reply); err != nil { return err }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isProtoMessage(v any) bool {\n    _, ok := v.(proto.Message)\n    if ok { return true }\n    rv := reflect.ValueOf(v)\n    for rv.Kind() == reflect.Pointer && !rv.IsNil() {\n        rv = rv.Elem()\n        if _, ok := rv.Interface().(proto.Message); ok { return true }\n    }\n    return false\n}","tryCatchPattern":"if err := codec.Unmarshal(data, target); err != nil {\n    if err.Error() == \"not proto message\" {\n        return fmt.Errorf(\"route negotiated proto codec but target %T is not a proto.Message\", target)\n    }\n    return err\n}","preventionTips":["Always pass pointers to protoc-generated messages (new protobuf API) as codec targets","Keep client and server codec/content-type negotiation aligned (proto with proto, json with json)","Generate code with the protoc-gen-go that matches google.golang.org/protobuf - avoid gogo/legacy types through this codec","Type-switch in generic layers and route only proto.Message targets to the proto codec"],"tags":["encoding","proto","codec","type-mismatch"],"backgroundTag":null,"analyzedSha":"668db92c2c001e9552594ba5a8aede8456af6d7e","analyzedAt":"2026-08-16T02:07:20.704Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}