@@ -202,8 +202,8 @@ public async Task SendEnvelopeAsync_ResponseRequestEntityTooLargeWithoutPathDefi
202202 public async Task SendEnvelopeAsync_ResponseNotOkWithStringMessage_LogsError ( )
203203 {
204204 // Arrange
205- const HttpStatusCode expectedCode = HttpStatusCode . RequestEntityTooLarge ;
206- const string expectedMessage = "413 Request Entity Too Large " ;
205+ const HttpStatusCode expectedCode = HttpStatusCode . InternalServerError ;
206+ const string expectedMessage = "500 Internal Server Error " ;
207207
208208 var httpHandler = Substitute . For < MockableHttpMessageHandler > ( ) ;
209209
@@ -483,9 +483,9 @@ public async Task SendEnvelopeAsync_Fails_RestoresDiscardedEventCounts()
483483 { DiscardReason . EventProcessor . WithCategory ( DataCategory . Error ) , 2 } ,
484484 { DiscardReason . QueueOverflow . WithCategory ( DataCategory . Security ) , 3 } ,
485485
486- // We also expect two new items recorded, due to the forced network failure.
487- { DiscardReason . NetworkError . WithCategory ( DataCategory . Error ) , 1 } , // from the event
488- { DiscardReason . NetworkError . WithCategory ( DataCategory . Default ) , 1 } // from the client report
486+ // We also expect two new items recorded, due to the forced HTTP failure.
487+ { DiscardReason . SendError . WithCategory ( DataCategory . Error ) , 1 } , // from the event
488+ { DiscardReason . SendError . WithCategory ( DataCategory . Default ) , 1 } // from the client report
489489 } ) ;
490490 }
491491
@@ -885,4 +885,108 @@ public async Task SendEnvelopeAsync_RateLimited_CallsBackpressureMonitor()
885885 backpressureMonitor . LastRateLimitEventTicks . Should ( ) . Be ( _fakeClock . GetUtcNow ( ) . Ticks ) ;
886886 backpressureMonitor . IsHealthy . Should ( ) . BeFalse ( ) ;
887887 }
888+
889+ [ Fact ]
890+ public async Task SendEnvelopeAsync_Response413WithJsonMessage_LogsSizeLimitError ( )
891+ {
892+ // Arrange
893+ const string expectedDetail = "Envelope too large" ;
894+ var expectedCauses = new [ ] { "max size exceeded" } ;
895+
896+ var httpHandler = Substitute . For < MockableHttpMessageHandler > ( ) ;
897+
898+ httpHandler . VerifiableSendAsync ( Arg . Any < HttpRequestMessage > ( ) , Arg . Any < CancellationToken > ( ) )
899+ . Returns ( _ => SentryResponses . GetJsonErrorResponse ( HttpStatusCode . RequestEntityTooLarge , expectedDetail , expectedCauses ) ) ;
900+
901+ var logger = new InMemoryDiagnosticLogger ( ) ;
902+
903+ var httpTransport = new HttpTransport (
904+ new SentryOptions
905+ {
906+ Dsn = ValidDsn ,
907+ Debug = true ,
908+ DiagnosticLogger = logger
909+ } ,
910+ new HttpClient ( httpHandler ) ) ;
911+
912+ var envelope = Envelope . FromEvent ( new SentryEvent ( ) ) ;
913+
914+ // Act
915+ await httpTransport . SendEnvelopeAsync ( envelope ) ;
916+
917+ // Assert
918+ var errorEntry = logger . Entries . FirstOrDefault ( e =>
919+ e . Level == SentryLevel . Error &&
920+ e . Message . Contains ( "exceeded the maximum allowed size" ) ) ;
921+
922+ errorEntry . Should ( ) . NotBeNull ( ) ;
923+ errorEntry ! . Message . Should ( ) . Contain ( "Consider reducing attachment sizes" ) ;
924+ errorEntry . Args [ 2 ] . ToString ( ) . Should ( ) . Contain ( expectedDetail ) ;
925+ errorEntry . Args [ 2 ] . ToString ( ) . Should ( ) . Contain ( expectedCauses [ 0 ] ) ;
926+ }
927+
928+ [ Fact ]
929+ public async Task SendEnvelopeAsync_Response413WithTextMessage_LogsSizeLimitError ( )
930+ {
931+ // Arrange
932+ const string expectedMessage = "413 Request Entity Too Large" ;
933+
934+ var httpHandler = Substitute . For < MockableHttpMessageHandler > ( ) ;
935+
936+ httpHandler . VerifiableSendAsync ( Arg . Any < HttpRequestMessage > ( ) , Arg . Any < CancellationToken > ( ) )
937+ . Returns ( _ => SentryResponses . GetTextErrorResponse ( HttpStatusCode . RequestEntityTooLarge , expectedMessage ) ) ;
938+
939+ var logger = new InMemoryDiagnosticLogger ( ) ;
940+
941+ var httpTransport = new HttpTransport (
942+ new SentryOptions
943+ {
944+ Dsn = ValidDsn ,
945+ Debug = true ,
946+ DiagnosticLogger = logger
947+ } ,
948+ new HttpClient ( httpHandler ) ) ;
949+
950+ var envelope = Envelope . FromEvent ( new SentryEvent ( ) ) ;
951+
952+ // Act
953+ await httpTransport . SendEnvelopeAsync ( envelope ) ;
954+
955+ // Assert
956+ var errorEntry = logger . Entries . FirstOrDefault ( e =>
957+ e . Level == SentryLevel . Error &&
958+ e . Message . Contains ( "exceeded the maximum allowed size" ) ) ;
959+
960+ errorEntry . Should ( ) . NotBeNull ( ) ;
961+ errorEntry ! . Message . Should ( ) . Contain ( "Consider reducing attachment sizes" ) ;
962+ errorEntry . Args [ 2 ] . ToString ( ) . Should ( ) . Contain ( expectedMessage ) ;
963+ }
964+
965+ [ Fact ]
966+ public async Task SendEnvelopeAsync_Response413_RecordsSendErrorDiscard ( )
967+ {
968+ // Arrange
969+ using var httpHandler = new RecordingHttpMessageHandler (
970+ new FakeHttpMessageHandler (
971+ ( ) => SentryResponses . GetJsonErrorResponse ( HttpStatusCode . RequestEntityTooLarge , "Too large" ) ) ) ;
972+
973+ var options = new SentryOptions
974+ {
975+ Dsn = ValidDsn ,
976+ DiagnosticLogger = _testOutputLogger ,
977+ SendClientReports = true ,
978+ Debug = true
979+ } ;
980+
981+ var httpTransport = new HttpTransport ( options , new HttpClient ( httpHandler ) ) ;
982+
983+ var recorder = ( ClientReportRecorder ) options . ClientReportRecorder ;
984+
985+ // Act
986+ await httpTransport . SendEnvelopeAsync ( Envelope . FromEvent ( new SentryEvent ( ) ) ) ;
987+
988+ // Assert - should use SendError, not NetworkError
989+ recorder . DiscardedEvents . Should ( ) . ContainKey ( DiscardReason . SendError . WithCategory ( DataCategory . Error ) ) ;
990+ recorder . DiscardedEvents . Should ( ) . NotContainKey ( DiscardReason . NetworkError . WithCategory ( DataCategory . Error ) ) ;
991+ }
888992}
0 commit comments