diff --git a/conn_http.go b/conn_http.go index 7436bcfc00..86968a02ed 100644 --- a/conn_http.go +++ b/conn_http.go @@ -443,6 +443,10 @@ func (h *httpConnect) readData(reader *chproto.Reader, timezone *time.Location, // Try to decode the block if err := block.Decode(reader, h.revision); err != nil { + if errors.Is(err, io.EOF) && (captureBuffer == nil || !bytes.Contains(captureBuffer.Bytes(), []byte("__exception__"))) { + return nil, io.EOF + } + // Decode failed - check if captured data contains exception marker // The decode error typically happens because it tries to read the // "__exception__" marker as binary data @@ -461,7 +465,7 @@ func (h *httpConnect) readData(reader *chproto.Reader, timezone *time.Location, if len(remaining) > 0 && captureBuffer != nil { captureBuffer.Write(remaining) } - if readErr != nil { + if readErr != nil && !errors.Is(readErr, io.EOF) { h.logger.Error("HTTP read data: decode error while parsing exception block", slog.Any("error", err)) } diff --git a/conn_http_exception_test.go b/conn_http_exception_test.go index 616ddb3386..ecbb2e2a0f 100644 --- a/conn_http_exception_test.go +++ b/conn_http_exception_test.go @@ -5,6 +5,8 @@ import ( "errors" "strings" "testing" + + chproto "github.com/ClickHouse/ch-go/proto" ) func TestParseExceptionFromBytes(t *testing.T) { @@ -287,3 +289,22 @@ func TestCapturingReader(t *testing.T) { }) } } + +func TestHTTPReadDataEOFDoesNotLogDecodeError(t *testing.T) { + var logBuf bytes.Buffer + h := &httpConnect{ + logger: slog.New(slog.NewTextHandler(&logBuf, &slog.HandlerOptions{Level: slog.LevelDebug})), + } + + reader := chproto.NewReader(bytes.NewReader(nil)) + block, err := h.readData(reader, nil, &bytes.Buffer{}) + if !errors.Is(err, io.EOF) { + t.Fatalf("expected io.EOF, got %v", err) + } + if block != nil { + t.Fatalf("expected nil block, got %#v", block) + } + if got := logBuf.String(); got != "" { + t.Fatalf("expected no error log, got %q", got) + } +}