From 55d58a3595bee76e9df3f6f229bb368cff24d597 Mon Sep 17 00:00:00 2001 From: Pawel Smolenski Date: Mon, 8 Dec 2025 17:06:41 +0100 Subject: [PATCH 1/2] Fix in proxy/server/target for io.EOF --- proxy/server/target.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/proxy/server/target.go b/proxy/server/target.go index 5a25f798..cd555e59 100644 --- a/proxy/server/target.go +++ b/proxy/server/target.go @@ -232,7 +232,7 @@ func (s *TargetStream) Run(nonce uint32, replyChan chan *pb.ProxyReply) { for { msg := s.serviceMethod.NewReply() err := grpcStream.RecvMsg(msg) - if err == io.EOF { + if isEOF(err) { return nil } if err != nil { @@ -321,7 +321,7 @@ func (s *TargetStream) Run(nonce uint32, replyChan chan *pb.ProxyReply) { // would cancel the errgroup early. Instead, we // can return nil, and the error will be picked // up by the receiving goroutine - if err == io.EOF { + if isEOF(err) { return nil } // Otherwise, this is the 'final' error. The underlying @@ -679,3 +679,13 @@ func (u *unconnectedClientStream) SendMsg(interface{}) error { func (u *unconnectedClientStream) RecvMsg(interface{}) error { return fmt.Errorf("%w: RecvMsg", errUnconnectedClient) } + +func isEOF(err error) bool { + // grpc-go 1.75 and older + if err == io.EOF { + return true + } + + // grpc-go 1.76+ + return status.Code(err) == codes.Internal && err.Error() == "cardinality violation: received no response message from non-server-streaming RPC" +} From c200cdd7706911d6f688aeba785a7d4316da9e32 Mon Sep 17 00:00:00 2001 From: Pawel Smolenski Date: Mon, 8 Dec 2025 21:33:51 +0100 Subject: [PATCH 2/2] Fixed detecting EOF in grpc-go 1.76 --- proxy/server/target.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proxy/server/target.go b/proxy/server/target.go index cd555e59..d8ee5a1e 100644 --- a/proxy/server/target.go +++ b/proxy/server/target.go @@ -22,6 +22,7 @@ import ( "fmt" "io" "math/rand" + "strings" "sync" "time" @@ -687,5 +688,5 @@ func isEOF(err error) bool { } // grpc-go 1.76+ - return status.Code(err) == codes.Internal && err.Error() == "cardinality violation: received no response message from non-server-streaming RPC" + return status.Code(err) == codes.Internal && strings.HasSuffix(err.Error(), "cardinality violation: received no response message from non-server-streaming RPC") }