This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new af495a9bf0c branch-4.1: [fix](be) Report stream load size limits in 
MiB #66224 (#66351)
af495a9bf0c is described below

commit af495a9bf0cdaee76a4c0f722f0b98668864154a
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Aug 5 16:29:40 2026 +0800

    branch-4.1: [fix](be) Report stream load size limits in MiB #66224 (#66351)
    
    Cherry-picked from #66224
    
    Co-authored-by: Refrain <[email protected]>
---
 be/src/service/http/action/http_stream.cpp | 13 ++++--
 be/src/service/http/action/stream_load.cpp | 23 ++++++----
 be/test/service/http/stream_load_test.cpp  | 74 +++++++++++++++++++++++++++++-
 3 files changed, 97 insertions(+), 13 deletions(-)

diff --git a/be/src/service/http/action/http_stream.cpp 
b/be/src/service/http/action/http_stream.cpp
index e519a62779f..8509a187014 100644
--- a/be/src/service/http/action/http_stream.cpp
+++ b/be/src/service/http/action/http_stream.cpp
@@ -67,6 +67,8 @@ using namespace ErrorCode;
 
 namespace {
 
+constexpr size_t MEBIBYTE = 1024 * 1024;
+
 bool is_compressed_file_scan(const TPipelineFragmentParams& params) {
     if (!params.__isset.file_scan_params) {
         return false;
@@ -231,7 +233,8 @@ Status HttpStreamAction::_on_header(HttpRequest* http_req, 
std::shared_ptr<Strea
     // TODO(zs) : need Need to request an FE to obtain information such as 
format
     // check content length
     ctx->body_bytes = 0;
-    size_t csv_max_body_bytes = config::streaming_load_max_mb * 1024 * 1024;
+    const auto csv_max_body_mb = config::streaming_load_max_mb;
+    size_t csv_max_body_bytes = csv_max_body_mb * MEBIBYTE;
     if (!http_req->header(HttpHeaders::CONTENT_LENGTH).empty()) {
         try {
             ctx->body_bytes = 
std::stol(http_req->header(HttpHeaders::CONTENT_LENGTH));
@@ -243,9 +246,11 @@ Status HttpStreamAction::_on_header(HttpRequest* http_req, 
std::shared_ptr<Strea
         if (ctx->body_bytes > csv_max_body_bytes) {
             LOG(WARNING) << "body exceed max size." << ctx->brief();
             return Status::Error<ErrorCode::EXCEEDED_LIMIT>(
-                    "body size {} exceed BE's conf `streaming_load_max_mb` {}. 
increase it if you "
-                    "are sure this load is reasonable",
-                    ctx->body_bytes, csv_max_body_bytes);
+                    "body size {} bytes ({:.2f} MiB) exceeds the limit of {} 
bytes ({} MiB) set "
+                    "by BE config `streaming_load_max_mb`. Increase it if you 
are sure this load "
+                    "is reasonable",
+                    ctx->body_bytes, static_cast<double>(ctx->body_bytes) / 
MEBIBYTE,
+                    csv_max_body_bytes, csv_max_body_mb);
         }
     }
 
diff --git a/be/src/service/http/action/stream_load.cpp 
b/be/src/service/http/action/stream_load.cpp
index 553f2664685..c391895cc5c 100644
--- a/be/src/service/http/action/stream_load.cpp
+++ b/be/src/service/http/action/stream_load.cpp
@@ -81,6 +81,7 @@ bvar::LatencyRecorder 
g_stream_load_commit_and_publish_latency_ms("stream_load",
                                                                   
"commit_and_publish_ms");
 
 static constexpr size_t MIN_CHUNK_SIZE = 64 * 1024;
+static constexpr size_t MEBIBYTE = 1024 * 1024;
 static const std::string CHUNK = "chunked";
 static const std::string OFF_MODE = "off_mode";
 static const std::string SYNC_MODE = "sync_mode";
@@ -290,8 +291,10 @@ Status StreamLoadAction::_on_header(HttpRequest* http_req, 
std::shared_ptr<Strea
 
     // check content length
     ctx->body_bytes = 0;
-    size_t csv_max_body_bytes = config::streaming_load_max_mb * 1024 * 1024;
-    size_t json_max_body_bytes = config::streaming_load_json_max_mb * 1024 * 
1024;
+    const auto csv_max_body_mb = config::streaming_load_max_mb;
+    size_t csv_max_body_bytes = csv_max_body_mb * MEBIBYTE;
+    const auto json_max_body_mb = config::streaming_load_json_max_mb;
+    size_t json_max_body_bytes = json_max_body_mb * MEBIBYTE;
     bool read_json_by_line = false;
     if (!http_req->header(HTTP_READ_JSON_BY_LINE).empty()) {
         if (iequal(http_req->header(HTTP_READ_JSON_BY_LINE), "true")) {
@@ -309,17 +312,21 @@ Status StreamLoadAction::_on_header(HttpRequest* 
http_req, std::shared_ptr<Strea
         if ((ctx->format == TFileFormatType::FORMAT_JSON) &&
             (ctx->body_bytes > json_max_body_bytes) && !read_json_by_line) {
             return Status::Error<ErrorCode::EXCEEDED_LIMIT>(
-                    "json body size {} exceed BE's conf 
`streaming_load_json_max_mb` {}. increase "
-                    "it if you are sure this load is reasonable",
-                    ctx->body_bytes, json_max_body_bytes);
+                    "json body size {} bytes ({:.2f} MiB) exceeds the limit of 
{} bytes ({} MiB) "
+                    "set by BE's conf streaming_load_json_max_mb. Increase it 
if you are sure "
+                    "this load is reasonable",
+                    ctx->body_bytes, static_cast<double>(ctx->body_bytes) / 
MEBIBYTE,
+                    json_max_body_bytes, json_max_body_mb);
         }
         // csv max body size
         else if (ctx->body_bytes > csv_max_body_bytes) {
             LOG(WARNING) << "body exceed max size." << ctx->brief();
             return Status::Error<ErrorCode::EXCEEDED_LIMIT>(
-                    "body size {} exceed BE's conf `streaming_load_max_mb` {}. 
increase it if you "
-                    "are sure this load is reasonable",
-                    ctx->body_bytes, csv_max_body_bytes);
+                    "body size {} bytes ({:.2f} MiB) exceeds the limit of {} 
bytes ({} MiB) set "
+                    "by BE's conf streaming_load_max_mb. Increase it if you 
are sure this load is "
+                    "reasonable",
+                    ctx->body_bytes, static_cast<double>(ctx->body_bytes) / 
MEBIBYTE,
+                    csv_max_body_bytes, csv_max_body_mb);
         }
     } else {
 #ifndef BE_TEST
diff --git a/be/test/service/http/stream_load_test.cpp 
b/be/test/service/http/stream_load_test.cpp
index 1ed2a1307bb..93dd9d044c7 100644
--- a/be/test/service/http/stream_load_test.cpp
+++ b/be/test/service/http/stream_load_test.cpp
@@ -28,7 +28,9 @@
 #include "event2/http_struct.h"
 #include "evhttp.h"
 #include "load/group_commit/wal/wal_manager.h"
+#include "load/stream_load/stream_load_context.h"
 #include "runtime/exec_env.h"
+#include "service/http/action/http_stream.h"
 #include "service/http/ev_http_server.h"
 #include "service/http/http_channel.h"
 #include "service/http/http_common.h"
@@ -37,6 +39,7 @@
 #include "service/http/http_headers.h"
 #include "service/http/http_request.h"
 #include "service/http/utils.h"
+#include "util/defer_op.h"
 
 namespace doris {
 
@@ -123,4 +126,73 @@ TEST_F(StreamLoadTest, TestHeader) {
         evhttp_request_free(evhttp_req);
     }
 }
-} // namespace doris
\ No newline at end of file
+
+TEST_F(StreamLoadTest, JsonBodySizeLimitPlusOneErrorIncludesExactBytes) {
+    const auto original_json_max_mb = config::streaming_load_json_max_mb;
+    Defer restore_json_max_mb {
+            [original_json_max_mb] { config::streaming_load_json_max_mb = 
original_json_max_mb; }};
+    config::streaming_load_json_max_mb = 100;
+
+    auto* evhttp_req = evhttp_request_new(nullptr, nullptr);
+    HttpRequest req(evhttp_req);
+    req.set_header(HttpHeaders::AUTHORIZATION, "Basic cm9vdDo=");
+    req.set_header(HTTP_FORMAT_KEY, "json");
+    req.set_header(HttpHeaders::CONTENT_LENGTH, "104857601");
+
+    StreamLoadAction action(nullptr);
+    auto ctx = std::make_shared<StreamLoadContext>(nullptr);
+    auto status = action._on_header(&req, ctx);
+
+    EXPECT_TRUE(status.is<ErrorCode::EXCEEDED_LIMIT>());
+    EXPECT_EQ(status.to_string_no_stack(),
+              "[E-217]json body size 104857601 bytes (100.00 MiB) exceeds the 
limit of 104857600 "
+              "bytes (100 MiB) set by BE's conf streaming_load_json_max_mb. 
Increase it if you "
+              "are sure this load is reasonable");
+    evhttp_request_free(evhttp_req);
+}
+
+TEST_F(StreamLoadTest, CsvBodySizeLimitPlusOneErrorIncludesExactBytes) {
+    const auto original_max_mb = config::streaming_load_max_mb;
+    Defer restore_max_mb {[original_max_mb] { config::streaming_load_max_mb = 
original_max_mb; }};
+    config::streaming_load_max_mb = 100;
+
+    auto* evhttp_req = evhttp_request_new(nullptr, nullptr);
+    HttpRequest req(evhttp_req);
+    req.set_header(HttpHeaders::AUTHORIZATION, "Basic cm9vdDo=");
+    req.set_header(HTTP_FORMAT_KEY, "csv");
+    req.set_header(HttpHeaders::CONTENT_LENGTH, "104857601");
+
+    StreamLoadAction action(nullptr);
+    auto ctx = std::make_shared<StreamLoadContext>(nullptr);
+    auto status = action._on_header(&req, ctx);
+
+    EXPECT_TRUE(status.is<ErrorCode::EXCEEDED_LIMIT>());
+    EXPECT_EQ(status.to_string_no_stack(),
+              "[E-217]body size 104857601 bytes (100.00 MiB) exceeds the limit 
of 104857600 bytes "
+              "(100 MiB) set by BE's conf streaming_load_max_mb. Increase it 
if you are sure this "
+              "load is reasonable");
+    evhttp_request_free(evhttp_req);
+}
+
+TEST_F(StreamLoadTest, HttpStreamBodySizeLimitPlusOneErrorIncludesExactBytes) {
+    const auto original_max_mb = config::streaming_load_max_mb;
+    Defer restore_max_mb {[original_max_mb] { config::streaming_load_max_mb = 
original_max_mb; }};
+    config::streaming_load_max_mb = 100;
+
+    auto* evhttp_req = evhttp_request_new(nullptr, nullptr);
+    HttpRequest req(evhttp_req);
+    req.set_header(HttpHeaders::AUTHORIZATION, "Basic cm9vdDo=");
+    req.set_header(HttpHeaders::CONTENT_LENGTH, "104857601");
+
+    HttpStreamAction action(nullptr);
+    auto ctx = std::make_shared<StreamLoadContext>(nullptr);
+    auto status = action._on_header(&req, ctx);
+
+    EXPECT_TRUE(status.is<ErrorCode::EXCEEDED_LIMIT>());
+    EXPECT_EQ(status.to_string_no_stack(),
+              "[E-217]body size 104857601 bytes (100.00 MiB) exceeds the limit 
of 104857600 bytes "
+              "(100 MiB) set by BE config `streaming_load_max_mb`. Increase it 
if you are sure "
+              "this load is reasonable");
+    evhttp_request_free(evhttp_req);
+}
+} // namespace doris


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to