@@ -806,12 +806,18 @@ describe('SentryEventWorker', () => {
806806 event_id : '4c40fee730194a989439a86bf75634111' ,
807807 sent_at : '2025-08-29T10:59:29.952Z' ,
808808 /* eslint-enable @typescript-eslint/naming-convention */
809- sdk : { name : 'sentry.javascript.react' , version : '9.10.1' } ,
809+ sdk : {
810+ name : 'sentry.javascript.react' ,
811+ version : '9.10.1' ,
812+ } ,
810813 } ) ,
811814 // Event item header
812815 JSON . stringify ( { type : 'event' } ) ,
813816 // Event item payload
814- JSON . stringify ( { message : 'Test event' , level : 'error' } ) ,
817+ JSON . stringify ( {
818+ message : 'Test event' ,
819+ level : 'error' ,
820+ } ) ,
815821 // Replay event item header - should be filtered out
816822 JSON . stringify ( { type : 'replay_event' } ) ,
817823 // Replay event item payload - should be filtered out
@@ -822,7 +828,10 @@ describe('SentryEventWorker', () => {
822828 /* eslint-enable @typescript-eslint/naming-convention */
823829 } ) ,
824830 // Replay recording item header - should be filtered out
825- JSON . stringify ( { type : 'replay_recording' , length : 343 } ) ,
831+ JSON . stringify ( {
832+ type : 'replay_recording' ,
833+ length : 343 ,
834+ } ) ,
826835 // Replay recording binary payload - should be filtered out
827836 'binary-data-here-that-is-not-json' ,
828837 ] ;
@@ -841,6 +850,7 @@ describe('SentryEventWorker', () => {
841850 expect ( mockedAmqpChannel . sendToQueue ) . toHaveBeenCalledTimes ( 1 ) ;
842851
843852 const addedTaskPayload = getAddTaskPayloadFromLastCall ( ) ;
853+
844854 expect ( addedTaskPayload ) . toMatchObject ( {
845855 payload : expect . objectContaining ( {
846856 addons : {
@@ -852,6 +862,90 @@ describe('SentryEventWorker', () => {
852862 } ) ,
853863 } ) ;
854864 } ) ;
865+
866+ it ( 'should ignore envelope with only replay_event and replay_recording items' , async ( ) => {
867+ /**
868+ * Test case based on real-world scenario where envelope contains only replay data
869+ * This should not crash with "Unexpected end of JSON input" error
870+ */
871+ const envelopeLines = [
872+ // Envelope header
873+ JSON . stringify ( {
874+ /* eslint-disable @typescript-eslint/naming-convention */
875+ event_id : '62680958b3ab4497886375e06533d86a' ,
876+ sent_at : '2025-12-24T13:16:34.580Z' ,
877+ /* eslint-enable @typescript-eslint/naming-convention */
878+ sdk : {
879+ name : 'sentry.javascript.react' ,
880+ version : '10.22.0' ,
881+ } ,
882+ } ) ,
883+ // Replay event item header - should be filtered out
884+ JSON . stringify ( { type : 'replay_event' } ) ,
885+ // Replay event item payload (large JSON) - should be filtered out
886+ JSON . stringify ( {
887+ /* eslint-disable @typescript-eslint/naming-convention */
888+ type : 'replay_event' ,
889+ replay_start_timestamp : 1766582182.757 ,
890+ timestamp : 1766582194.579 ,
891+ error_ids : [ ] ,
892+ trace_ids : [ ] ,
893+ urls : [ 'https://my.huntio.ru/applicants' , 'https://my.huntio.ru/applicants/1270067' ] ,
894+ replay_id : '62680958b3ab4497886375e06533d86a' ,
895+ segment_id : 1 ,
896+ replay_type : 'session' ,
897+ request : {
898+ url : 'https://my.huntio.ru/applicants/1270067' ,
899+ headers : {
900+ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' ,
901+ } ,
902+ } ,
903+ event_id : '62680958b3ab4497886375e06533d86a' ,
904+ environment : 'production' ,
905+ release : '1.0.7' ,
906+ sdk : {
907+ integrations : [ 'InboundFilters' , 'FunctionToString' , 'BrowserApiErrors' , 'Breadcrumbs' ] ,
908+ name : 'sentry.javascript.react' ,
909+ version : '10.22.0' ,
910+ settings : { infer_ip : 'auto' } ,
911+ } ,
912+ user : {
913+ id : 487 ,
914+ 915+ username : 'Прохорова Наталья' ,
916+ } ,
917+ contexts : { react : { version : '19.1.0' } } ,
918+ transaction : '/applicants/1270067' ,
919+ platform : 'javascript' ,
920+ /* eslint-enable @typescript-eslint/naming-convention */
921+ } ) ,
922+ // Replay recording item header - should be filtered out
923+ JSON . stringify ( {
924+ type : 'replay_recording' ,
925+ length : 16385 ,
926+ } ) ,
927+ /* eslint-disable @typescript-eslint/naming-convention */
928+ // Segment ID - should be filtered out
929+ JSON . stringify ( { segment_id : 1 } ) ,
930+ /* eslint-enable @typescript-eslint/naming-convention */
931+ // Binary data (simulated) - should be filtered out
932+ 'xnFWy@v$xAlJ=&fS~¾˶IJ<Dڒ%8yX]]ˣ·9V|JGd!+%fF' ,
933+ ] ;
934+
935+ const envelopeString = envelopeLines . join ( '\n' ) ;
936+
937+ // Should not throw "Unexpected end of JSON input" error
938+ await worker . handle ( {
939+ payload : {
940+ envelope : b64encode ( envelopeString ) ,
941+ } ,
942+ projectId : '123' ,
943+ catcherType : 'external/sentry' ,
944+ } ) ;
945+
946+ // Should not send any tasks since all items were replay-related and filtered out
947+ expect ( mockedAmqpChannel . sendToQueue ) . not . toHaveBeenCalled ( ) ;
948+ } ) ;
855949 } ) ;
856950
857951 describe ( 'envelope parsing' , ( ) => {
0 commit comments