From 3ea9d86c5c340c3912e38145656ea52843f2bd25 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Fri, 4 Oct 2024 18:08:48 +0000 Subject: [PATCH 01/10] Avoid returning 500 when for TRACE_TOO_LARGE --- modules/frontend/pipeline/sync_handler_adjust_response_code.go | 3 ++- modules/querier/http.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/frontend/pipeline/sync_handler_adjust_response_code.go b/modules/frontend/pipeline/sync_handler_adjust_response_code.go index a7c9a362af1..e9d6a3ab39f 100644 --- a/modules/frontend/pipeline/sync_handler_adjust_response_code.go +++ b/modules/frontend/pipeline/sync_handler_adjust_response_code.go @@ -44,8 +44,9 @@ func (c statusCodeAdjustWare) RoundTrip(req Request) (*http.Response, error) { // if the frontend issues a bad request then externally we need to represent that as an // internal error // exceptions + // 413 - request entity too large // 429 - too many requests - if resp.StatusCode >= 400 && resp.StatusCode < 500 && resp.StatusCode != 429 { + if resp.StatusCode >= 400 && resp.StatusCode < 500 && resp.StatusCode != 429 && resp.StatusCode != 413 { resp.StatusCode = http.StatusInternalServerError resp.Status = http.StatusText(http.StatusInternalServerError) // leave the body alone. it will preserve the original error message diff --git a/modules/querier/http.go b/modules/querier/http.go index 247d512445f..307c65c3af0 100644 --- a/modules/querier/http.go +++ b/modules/querier/http.go @@ -427,7 +427,7 @@ func handleError(w http.ResponseWriter, err error) { // todo: better understand all errors returned from queriers and categorize more as 4XX if errors.Is(err, trace.ErrTraceTooLarge) { - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, err.Error(), http.StatusRequestEntityTooLarge) return } From 49072c39b95b7c471ea9bcc762baa23bcae0ee5f Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 15 Oct 2024 19:40:26 +0000 Subject: [PATCH 02/10] Test for frontend return of 413 --- integration/e2e/limits_test.go | 6 +++--- modules/frontend/handler.go | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/integration/e2e/limits_test.go b/integration/e2e/limits_test.go index 0110dd32cef..f47420eaa53 100644 --- a/integration/e2e/limits_test.go +++ b/integration/e2e/limits_test.go @@ -234,11 +234,11 @@ func TestQueryLimits(t *testing.T) { _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, "trace exceeds max size") - require.ErrorContains(t, err, "failed with response: 500") // confirm frontend returns 500 + require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 413 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, "trace exceeds max size") - require.ErrorContains(t, err, "failed with response: 500") // todo: this should return 400 ideally so the frontend does not retry, but does not currently + require.ErrorContains(t, err, "failed with response: 413") // complete block timeout is 10 seconds time.Sleep(15 * time.Second) @@ -248,7 +248,7 @@ func TestQueryLimits(t *testing.T) { _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, "trace exceeds max size") - require.ErrorContains(t, err, "failed with response: 400") // confirm querier returns 400 + require.ErrorContains(t, err, "failed with response: 413") // confirm querier returns 400 } func TestLimitsPartialSuccess(t *testing.T) { diff --git a/modules/frontend/handler.go b/modules/frontend/handler.go index 4a9fbe2e3ff..0236c6a176b 100644 --- a/modules/frontend/handler.go +++ b/modules/frontend/handler.go @@ -32,6 +32,7 @@ var ( errCanceled = httpgrpc.Errorf(StatusClientClosedRequest, context.Canceled.Error()) errDeadlineExceeded = httpgrpc.Errorf(http.StatusGatewayTimeout, context.DeadlineExceeded.Error()) errRequestEntityTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "http: request body too large") + errTraceTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "body: trace too large") ) // handler exists to wrap a roundtripper with an HTTP handler. It wraps all @@ -163,6 +164,8 @@ func writeError(w http.ResponseWriter, err error) error { err = errDeadlineExceeded } else if isRequestBodyTooLarge(err) { err = errRequestEntityTooLarge + } else if isTraceTooLarge(err) { + err = errTraceTooLarge } httpgrpc.WriteError(w, err) return err @@ -172,3 +175,7 @@ func writeError(w http.ResponseWriter, err error) error { func isRequestBodyTooLarge(err error) bool { return err != nil && strings.Contains(err.Error(), "http: request body too large") } + +func isTraceTooLarge(err error) bool { + return err != nil && strings.Contains(err.Error(), "body: trace exceeds max size") +} From 2e3bdf544f842ea5fa809a3ee7098b1bcb2f0921 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Tue, 15 Oct 2024 20:45:34 +0000 Subject: [PATCH 03/10] Check the GRPC message content as well --- integration/e2e/limits_test.go | 2 +- modules/frontend/handler.go | 4 ++-- modules/querier/http.go | 6 ++++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/integration/e2e/limits_test.go b/integration/e2e/limits_test.go index f47420eaa53..59ca18a862a 100644 --- a/integration/e2e/limits_test.go +++ b/integration/e2e/limits_test.go @@ -244,7 +244,7 @@ func TestQueryLimits(t *testing.T) { time.Sleep(15 * time.Second) _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, "trace exceeds max size") - require.ErrorContains(t, err, "failed with response: 500") // confirm frontend returns 500 + require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 500 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, "trace exceeds max size") diff --git a/modules/frontend/handler.go b/modules/frontend/handler.go index 0236c6a176b..4b3aa6ff48a 100644 --- a/modules/frontend/handler.go +++ b/modules/frontend/handler.go @@ -32,7 +32,7 @@ var ( errCanceled = httpgrpc.Errorf(StatusClientClosedRequest, context.Canceled.Error()) errDeadlineExceeded = httpgrpc.Errorf(http.StatusGatewayTimeout, context.DeadlineExceeded.Error()) errRequestEntityTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "http: request body too large") - errTraceTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "body: trace too large") + errTraceTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "http: trace exceeds max size") ) // handler exists to wrap a roundtripper with an HTTP handler. It wraps all @@ -177,5 +177,5 @@ func isRequestBodyTooLarge(err error) bool { } func isTraceTooLarge(err error) bool { - return err != nil && strings.Contains(err.Error(), "body: trace exceeds max size") + return err != nil && strings.Contains(err.Error(), "trace exceeds max size") } diff --git a/modules/querier/http.go b/modules/querier/http.go index 307c65c3af0..733aad0ac8c 100644 --- a/modules/querier/http.go +++ b/modules/querier/http.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "strings" "time" "github.com/golang/protobuf/jsonpb" //nolint:all //deprecated @@ -425,8 +426,9 @@ func handleError(w http.ResponseWriter, err error) { return } - // todo: better understand all errors returned from queriers and categorize more as 4XX - if errors.Is(err, trace.ErrTraceTooLarge) { + // TODO: better understand all errors returned from queriers and categorize more as 4XX + // NOTE: we receive a GRPC error from the ingesters, and so we need to check the string content of error as well. + if errors.Is(err, trace.ErrTraceTooLarge) || strings.Contains(err.Error(), trace.ErrTraceTooLarge.Error()) { http.Error(w, err.Error(), http.StatusRequestEntityTooLarge) return } From cb333d0b9b1819af2d6e140a7cc8fe4afcbf489b Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Wed, 16 Oct 2024 19:57:38 +0000 Subject: [PATCH 04/10] Move status code rewrite to the frontend combiner for tracebyid --- modules/frontend/combiner/trace_by_id.go | 12 ++++++++++++ modules/frontend/handler.go | 7 ------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/modules/frontend/combiner/trace_by_id.go b/modules/frontend/combiner/trace_by_id.go index 24393bf8adb..671d61ce61c 100644 --- a/modules/frontend/combiner/trace_by_id.go +++ b/modules/frontend/combiner/trace_by_id.go @@ -2,6 +2,7 @@ package combiner import ( "bytes" + "errors" "fmt" "io" "net/http" @@ -83,6 +84,12 @@ func (c *traceByIDCombiner) AddResponse(r PipelineResponse) error { // Consume the trace _, err = c.c.Consume(resp.Trace) + + if errors.Is(err, trace.ErrTraceTooLarge) { + c.code = http.StatusRequestEntityTooLarge + c.statusMessage = trace.ErrTraceTooLarge.Error() + } + return err } @@ -156,6 +163,11 @@ func (c *traceByIDCombiner) shouldQuit() bool { return false } + // test special case for 413 + if c.code == http.StatusRequestEntityTooLarge { + return false + } + // bail on other 400s if c.code/100 == 4 { return true diff --git a/modules/frontend/handler.go b/modules/frontend/handler.go index 4b3aa6ff48a..4a9fbe2e3ff 100644 --- a/modules/frontend/handler.go +++ b/modules/frontend/handler.go @@ -32,7 +32,6 @@ var ( errCanceled = httpgrpc.Errorf(StatusClientClosedRequest, context.Canceled.Error()) errDeadlineExceeded = httpgrpc.Errorf(http.StatusGatewayTimeout, context.DeadlineExceeded.Error()) errRequestEntityTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "http: request body too large") - errTraceTooLarge = httpgrpc.Errorf(http.StatusRequestEntityTooLarge, "http: trace exceeds max size") ) // handler exists to wrap a roundtripper with an HTTP handler. It wraps all @@ -164,8 +163,6 @@ func writeError(w http.ResponseWriter, err error) error { err = errDeadlineExceeded } else if isRequestBodyTooLarge(err) { err = errRequestEntityTooLarge - } else if isTraceTooLarge(err) { - err = errTraceTooLarge } httpgrpc.WriteError(w, err) return err @@ -175,7 +172,3 @@ func writeError(w http.ResponseWriter, err error) error { func isRequestBodyTooLarge(err error) bool { return err != nil && strings.Contains(err.Error(), "http: request body too large") } - -func isTraceTooLarge(err error) bool { - return err != nil && strings.Contains(err.Error(), "trace exceeds max size") -} From 35e7aaedd1f5c59021f6782f210caa37c4f2933b Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Wed, 16 Oct 2024 19:57:53 +0000 Subject: [PATCH 05/10] Match the error string in tests --- integration/e2e/limits_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/integration/e2e/limits_test.go b/integration/e2e/limits_test.go index 59ca18a862a..3b3b6405ed5 100644 --- a/integration/e2e/limits_test.go +++ b/integration/e2e/limits_test.go @@ -26,6 +26,7 @@ import ( "github.com/grafana/tempo/integration/util" "github.com/grafana/tempo/pkg/httpclient" + "github.com/grafana/tempo/pkg/model/trace" "github.com/grafana/tempo/pkg/tempopb" tempoUtil "github.com/grafana/tempo/pkg/util" "github.com/grafana/tempo/pkg/util/test" @@ -233,21 +234,21 @@ func TestQueryLimits(t *testing.T) { querierClient := httpclient.New("http://"+tempo.Endpoint(3200)+"/querier", tempoUtil.FakeTenantID) _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) - require.ErrorContains(t, err, "trace exceeds max size") + require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 413 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) - require.ErrorContains(t, err, "trace exceeds max size") + require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) require.ErrorContains(t, err, "failed with response: 413") // complete block timeout is 10 seconds time.Sleep(15 * time.Second) _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) - require.ErrorContains(t, err, "trace exceeds max size") + require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 500 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) - require.ErrorContains(t, err, "trace exceeds max size") + require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) require.ErrorContains(t, err, "failed with response: 413") // confirm querier returns 400 } From 2107884750f48421f0ec606f40fcde585afb50c2 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Thu, 17 Oct 2024 20:40:03 +0000 Subject: [PATCH 06/10] Quit and not return an error --- modules/frontend/combiner/trace_by_id.go | 3 ++- modules/frontend/combiner/trace_by_id_test.go | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/frontend/combiner/trace_by_id.go b/modules/frontend/combiner/trace_by_id.go index 671d61ce61c..b16aafc8369 100644 --- a/modules/frontend/combiner/trace_by_id.go +++ b/modules/frontend/combiner/trace_by_id.go @@ -88,6 +88,7 @@ func (c *traceByIDCombiner) AddResponse(r PipelineResponse) error { if errors.Is(err, trace.ErrTraceTooLarge) { c.code = http.StatusRequestEntityTooLarge c.statusMessage = trace.ErrTraceTooLarge.Error() + return nil } return err @@ -165,7 +166,7 @@ func (c *traceByIDCombiner) shouldQuit() bool { // test special case for 413 if c.code == http.StatusRequestEntityTooLarge { - return false + return true } // bail on other 400s diff --git a/modules/frontend/combiner/trace_by_id_test.go b/modules/frontend/combiner/trace_by_id_test.go index 0f605de8640..ac83e8ead6e 100644 --- a/modules/frontend/combiner/trace_by_id_test.go +++ b/modules/frontend/combiner/trace_by_id_test.go @@ -48,15 +48,15 @@ func TestTraceByIDShouldQuit(t *testing.T) { should = c.ShouldQuit() require.False(t, should) - // trace too large, should not quit but should return an error + // trace too large, should quit and should not return an error c = NewTraceByID(1, api.HeaderAcceptJSON) err = c.AddResponse(toHTTPProtoResponse(t, &tempopb.TraceByIDResponse{ Trace: test.MakeTrace(1, nil), Metrics: &tempopb.TraceByIDMetrics{}, }, 200)) - require.Error(t, err) + require.NoError(t, err) should = c.ShouldQuit() - require.False(t, should) + require.True(t, should) } func TestTraceByIDHonorsContentType(t *testing.T) { From bd0604d09197ef8cfba2843e33840777b9feaacb Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Thu, 17 Oct 2024 20:45:43 +0000 Subject: [PATCH 07/10] Move from 413 to 422 after some discussion --- integration/e2e/limits_test.go | 8 ++++---- modules/frontend/combiner/trace_by_id.go | 6 +++--- .../pipeline/sync_handler_adjust_response_code.go | 4 ++-- modules/querier/http.go | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration/e2e/limits_test.go b/integration/e2e/limits_test.go index 3b3b6405ed5..2540214ccde 100644 --- a/integration/e2e/limits_test.go +++ b/integration/e2e/limits_test.go @@ -235,21 +235,21 @@ func TestQueryLimits(t *testing.T) { _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) - require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 413 + require.ErrorContains(t, err, "failed with response: 422") // confirm frontend returns 422 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) - require.ErrorContains(t, err, "failed with response: 413") + require.ErrorContains(t, err, "failed with response: 422") // complete block timeout is 10 seconds time.Sleep(15 * time.Second) _, err = client.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) - require.ErrorContains(t, err, "failed with response: 413") // confirm frontend returns 500 + require.ErrorContains(t, err, "failed with response: 422") // confirm frontend returns 422 _, err = querierClient.QueryTrace(tempoUtil.TraceIDToHexString(traceID[:])) require.ErrorContains(t, err, trace.ErrTraceTooLarge.Error()) - require.ErrorContains(t, err, "failed with response: 413") // confirm querier returns 400 + require.ErrorContains(t, err, "failed with response: 422") // confirm querier returns 422 } func TestLimitsPartialSuccess(t *testing.T) { diff --git a/modules/frontend/combiner/trace_by_id.go b/modules/frontend/combiner/trace_by_id.go index b16aafc8369..ab18fe29265 100644 --- a/modules/frontend/combiner/trace_by_id.go +++ b/modules/frontend/combiner/trace_by_id.go @@ -86,7 +86,7 @@ func (c *traceByIDCombiner) AddResponse(r PipelineResponse) error { _, err = c.c.Consume(resp.Trace) if errors.Is(err, trace.ErrTraceTooLarge) { - c.code = http.StatusRequestEntityTooLarge + c.code = http.StatusUnprocessableEntity c.statusMessage = trace.ErrTraceTooLarge.Error() return nil } @@ -164,8 +164,8 @@ func (c *traceByIDCombiner) shouldQuit() bool { return false } - // test special case for 413 - if c.code == http.StatusRequestEntityTooLarge { + // test special case for 422 + if c.code == http.StatusUnprocessableEntity { return true } diff --git a/modules/frontend/pipeline/sync_handler_adjust_response_code.go b/modules/frontend/pipeline/sync_handler_adjust_response_code.go index e9d6a3ab39f..2c06d55052a 100644 --- a/modules/frontend/pipeline/sync_handler_adjust_response_code.go +++ b/modules/frontend/pipeline/sync_handler_adjust_response_code.go @@ -44,9 +44,9 @@ func (c statusCodeAdjustWare) RoundTrip(req Request) (*http.Response, error) { // if the frontend issues a bad request then externally we need to represent that as an // internal error // exceptions - // 413 - request entity too large + // 422 - unprocessable entity // 429 - too many requests - if resp.StatusCode >= 400 && resp.StatusCode < 500 && resp.StatusCode != 429 && resp.StatusCode != 413 { + if resp.StatusCode >= 400 && resp.StatusCode < 500 && resp.StatusCode != 429 && resp.StatusCode != 422 { resp.StatusCode = http.StatusInternalServerError resp.Status = http.StatusText(http.StatusInternalServerError) // leave the body alone. it will preserve the original error message diff --git a/modules/querier/http.go b/modules/querier/http.go index 733aad0ac8c..bd10f03c746 100644 --- a/modules/querier/http.go +++ b/modules/querier/http.go @@ -429,7 +429,7 @@ func handleError(w http.ResponseWriter, err error) { // TODO: better understand all errors returned from queriers and categorize more as 4XX // NOTE: we receive a GRPC error from the ingesters, and so we need to check the string content of error as well. if errors.Is(err, trace.ErrTraceTooLarge) || strings.Contains(err.Error(), trace.ErrTraceTooLarge.Error()) { - http.Error(w, err.Error(), http.StatusRequestEntityTooLarge) + http.Error(w, err.Error(), http.StatusUnprocessableEntity) return } From 94a6eea6bfc1137f72d70b84f0ce91a54d32f8e1 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Thu, 17 Oct 2024 20:47:57 +0000 Subject: [PATCH 08/10] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a7e8d0f15..0ed04b3de2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * [CHANGE] No longer send the final diff in GRPC streaming. Instead we rely on the streamed intermediate results. [#4062](https://github.com/grafana/tempo/pull/4062) (@joe-elliott) * [CHANGE] Update Go to 1.23.1 [#4146](https://github.com/grafana/tempo/pull/4146) [#4147](https://github.com/grafana/tempo/pull/4147) (@javiermolinar) * [CHANGE] TraceQL: Add range condition for byte predicates [#4198](https://github.com/grafana/tempo/pull/4198) (@ie-pham) +* [CHANGE] Return 422 for TRACE_TOO_LARGE queries [#4160](https://github.com/grafana/tempo/pull/4160) (@zalegrala) * [FEATURE] Discarded span logging `log_discarded_spans` [#3957](https://github.com/grafana/tempo/issues/3957) (@dastrobu) * [FEATURE] TraceQL support for instrumentation scope [#3967](https://github.com/grafana/tempo/pull/3967) (@ie-pham) * [ENHANCEMENT] TraceQL: Attribute iterators collect matched array values [#3867](https://github.com/grafana/tempo/pull/3867) (@electron0zero, @stoewer) From 88dbf1a9de740b84327769051d8a93070656113d Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Fri, 18 Oct 2024 13:41:22 +0000 Subject: [PATCH 09/10] Update modules/frontend/combiner/trace_by_id.go Co-authored-by: Javier Molina Reyes --- modules/frontend/combiner/trace_by_id.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/frontend/combiner/trace_by_id.go b/modules/frontend/combiner/trace_by_id.go index ab18fe29265..082268bb00e 100644 --- a/modules/frontend/combiner/trace_by_id.go +++ b/modules/frontend/combiner/trace_by_id.go @@ -87,7 +87,7 @@ func (c *traceByIDCombiner) AddResponse(r PipelineResponse) error { if errors.Is(err, trace.ErrTraceTooLarge) { c.code = http.StatusUnprocessableEntity - c.statusMessage = trace.ErrTraceTooLarge.Error() + c.statusMessage = fmt.Sprint(err) return nil } From 6b088b6c3bf8836dbe8e541fa128f14c9d6ba4b7 Mon Sep 17 00:00:00 2001 From: Zach Leslie Date: Fri, 18 Oct 2024 13:48:19 +0000 Subject: [PATCH 10/10] Lint --- modules/frontend/combiner/trace_by_id.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/frontend/combiner/trace_by_id.go b/modules/frontend/combiner/trace_by_id.go index 082268bb00e..dfdd886f431 100644 --- a/modules/frontend/combiner/trace_by_id.go +++ b/modules/frontend/combiner/trace_by_id.go @@ -87,7 +87,7 @@ func (c *traceByIDCombiner) AddResponse(r PipelineResponse) error { if errors.Is(err, trace.ErrTraceTooLarge) { c.code = http.StatusUnprocessableEntity - c.statusMessage = fmt.Sprint(err) + c.statusMessage = fmt.Sprint(err) return nil }