Additional information.
The issues continue even after updating to the latest gRPC build:
- gRPC-protoc:31.1;gRPC-lib:1.80.0
Oh, I suppose it may be pertinent that this is occurring on a Windows
platform. While we are cross platform I have not checked behavior on Linux.
On Thursday, May 14, 2026 at 3:20:43 PM UTC-7 Rocha Stratovan wrote:
> I forgot to add.
>
> This is the log information I observed when I turned on
>
> *GRPC_VERBOSITY=DEBUG GRPC_TRACE=transport,http*
>
> I0513 16:05:24.558000000 50932 chttp2_transport.cc:2981] ipv4:
> 192.168.100.153:54010: Keepalive ping cancelled. Resetting timer.
> I0513 16:05:24.558000000 50932 chttp2_transport.cc:2814] ipv4:
> 192.168.100.153:54010: Complete BDP ping err=OK
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DC9F8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DD5F8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DBAF8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DCCF8]:
> CANCEL:CANCELLED
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DBEF8]:
> CANCEL:CANCELLED
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1623]
> perform_stream_op[s=000001F8A1A2EE50; op=000001F89F5DC1F8]:
> CANCEL:CANCELLED
> I0513 16:05:24.603000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DC9F8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}; on_complete = 000001F8A1ADFFC0
> D0513 16:05:24.603000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [RESOURCE_EXHAUSTED:SERVER: Received message larger than max (382267226 vs.
> 4194304) {grpc_status:8}]
> D0513 16:05:24.603000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=000001F8A1A2EE18 read_closed=1 write_closed=1 116726
> D0513 16:05:24.603000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:919] W:000001F8A19EBB20
> SERVER [ipv4:192.168.100.153:54010] state IDLE -> WRITING [CLOSE_FROM_API]
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1ADFFC0 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DD5F8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}; on_complete = 000001F8A1ADFF80
> D0513 16:05:24.604000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [RESOURCE_EXHAUSTED:SERVER: Received message larger than max (382267226 vs.
> 4194304) {grpc_status:8}]
> D0513 16:05:24.604000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1ADFF80 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DBAF8]:
> CANCEL:RESOURCE_EXHAUSTED:SERVER: Received message larger than max
> (382267226 vs. 4194304) {grpc_status:8}; on_complete = 000001F8A1ADF9C0
> D0513 16:05:24.604000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [RESOURCE_EXHAUSTED:SERVER: Received message larger than max (382267226 vs.
> 4194304) {grpc_status:8}]
> D0513 16:05:24.604000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1ADF9C0 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.604000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DCCF8]:
> CANCEL:CANCELLED; on_complete = 000001F8A1ADF300
> D0513 16:05:24.604000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [CANCELLED]
> D0513 16:05:24.605000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1ADF300 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DBEF8]:
> CANCEL:CANCELLED; on_complete = 000001F8A1A007B0
> D0513 16:05:24.605000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [CANCELLED]
> D0513 16:05:24.605000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1A007B0 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:1356]
> perform_stream_op_locked[s=000001F8A1A2EE50; op=000001F89F5DC1F8]:
> CANCEL:CANCELLED; on_complete = 000001F8A1A016B0
> D0513 16:05:24.605000000 62328 chttp2_transport.cc:2304]
> MARK_STREAM_CLOSED: t=000001F8A19EBB20 s=000001F8A1A2EE50(id=3) read+write
> [CANCELLED]
> D0513 16:05:24.605000000 62328 chttp2_transport.cc:2092]
> maybe_complete_recv_trailing_metadata cli=0 s=000001F8A1A2EE50
> closure=0000000000000000 read_closed=1 write_closed=1 0
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:1284]
> complete_closure_step: t=000001F8A19EBB20 000001F8A1A016B0 refs=0
> flags=0x0000 desc=op->on_complete err=OK write_state=WRITING
> whence=(null):-1
> I0513 16:05:24.605000000 62328 chttp2_transport.cc:919] W:000001F8A19EBB20
> SERVER [ipv4:192.168.100.153:54010] state WRITING -> WRITING [begin write
> in current thread]
> I0513 16:05:24.606000000 62328 chttp2_transport.cc:919] W:000001F8A19EBB20
> SERVER [ipv4:192.168.100.153:54010] state WRITING -> IDLE [finish writing]
>
> On Thursday, May 14, 2026 at 3:18:36 PM UTC-7 Rocha Stratovan wrote:
>
>> I am using gRPC versions:
>>
>> - gRPC-protoc:26.1
>> - gRPC-lib:1.63.0
>>
>>
>> *How can my C++ server code detect when the client has sent a message
>> that is larger than the server's maximum size (currently using the 4 MB
>> default).*
>> I know how to restart my server with a larger size to get this to work.
>> However, I want to be able to provide meaningful log information when this
>> happens.
>>
>> The current client / server environment is one where any time there is a
>> problem "*it's the servers fault*", and "*it's a hassle to reproduce the
>> problem with debug flags enabled.*"
>>
>> This is an example of the service my server is implementing.
>>
>> ```
>> rpc upload (stream StreamElement) returns (google.protobuf.Empty ) {}
>> ```
>>
>> And the basic skeleton of how the server works
>>
>> ```
>> grpc::Status
>> MyStream::upload(
>> grpc::ServerContext* context,
>> grpc::ServerReader<gRPCDicosStreamElement>* reader,
>> ::google::protobuf::Empty* response)
>> {
>> StreamElement element;
>>
>>
>> while(reader->Read(&element))
>> {
>> ... do stuff to receive the element
>> }
>>
>>
>> // Detect abnormal stream termination
>> if (context->IsCancelled())
>> {
>> ... do canceled stuff, logging, etc....
>> return grpc::Status(grpc::StatusCode::CANCELLED, "Client
>> cancelled");
>> }
>>
>> return grpc::Status::OK;
>> }
>> ```
>>
>>
>> I'm looking at DETECTING when a gRPC session is
>> stopped/canceled/killed/errored
>> because of a message size issue. I need to detect that this problem
>> happened so
>> my software can clearly instruct the user to restart the server with a
>> larger
>> size.
>>
>> The problem was originally observed as the following
>>
>>
>> 1. Client sends a streaming message to me, the server.
>> 2. Client sends a message that is larger than the 4 MB default.
>> 3. The client is ignoring the return status, and claims the server is
>> broken.
>> 4. After a long debugging session I learned about the client / server
>> message size conflict.
>>
>> On the server
>>
>> - I found that `read()` will return false because the stream has ended
>> - and surprisingly `context->IsCancelled()` will also return false.
>>
>>
>> So my server code thinks all is good, tries to process the accumulated
>> stream of data and fails.
>>
>> It appears the gRPC layer is detecting the problem, shutting things down
>> and not informing me, the server application.
>>
>> I tried using Message Interceptors to look into this further.
>>
>>
>> *Message Intercept Test #1 - PRE_SEND_STATUS*
>>
>> First I used the hook for *PRE_SEND_STATUS* to view the status, but I
>> found this was the status set/returned by my `upload()` logic.
>>
>>
>>
>> *Message Intercept Test #2 - EVERYTHING*
>> This is where things get interesting.
>>
>> I thought I would go big and so I created an interceptor that would *print
>> the current callback hook every time it's invoked*.
>>
>>
>>
>> *If I use my library's logging method I see:*
>>
>> 1. POST_RECV_INITIAL_METADATA
>> 2. followed by a ton of POST_RECV_MESSAGE
>> 3. And then logs from my code that triggers when the upload() logic
>> has completed. Part of which is an error about bad data received.
>>
>>
>> However, *if I use std::cerr and std::endl instead *of my library's
>> logging I see:
>>
>> 1. POST_RECV_INITIAL_METADATA
>> 2. followed by a ton of POST_RECV_MESSAGE
>> 3. Now, is_canceled() returns true and I get the expected desired
>> failure
>>
>>
>> Does anyone know how to do this correctly? I find it hard to believe that
>> the library layer doesn't propagate a failure condition like this up to the
>> application. I feel like I'm missing an API or method or pattern that would
>> help me with this.
>>
>> Thank you,
>>
>> John
>>
>
--
You received this message because you are subscribed to the Google Groups
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/grpc-io/2be75316-34c0-4d45-814c-5b86c52809a8n%40googlegroups.com.