@@ -412,28 +412,29 @@ def test_deobfuscate_exception_type_instance_of_pattern() -> None:
412
412
):
413
413
deobfuscate_exception_type (data )
414
414
415
- # Only exception types should be deobfuscated, values remain unchanged
415
+ # Exception types should be deobfuscated
416
416
assert data ["exception" ]["values" ][0 ]["type" ] == "NetworkException"
417
- assert data ["exception" ]["values" ][0 ]["value" ] == "Instance of 'xyz'"
417
+ # Value starts with pattern: quoted symbol should be deobfuscated
418
+ assert data ["exception" ]["values" ][0 ]["value" ] == "Instance of 'NetworkException'"
418
419
419
420
assert data ["exception" ]["values" ][1 ]["type" ] == "DatabaseException"
421
+ # Pattern can appear anywhere: deobfuscate occurrences
420
422
assert (
421
423
data ["exception" ]["values" ][1 ]["value" ]
422
- == "Unhandled Exception: Instance of 'abc ' was thrown"
424
+ == "Unhandled Exception: Instance of 'DatabaseException ' was thrown"
423
425
)
424
426
425
427
assert data ["exception" ]["values" ][2 ]["type" ] == "FileException"
426
- # No 'Instance of' pattern, so value should remain unchanged
428
+ # No pattern, value should remain unchanged
427
429
assert (
428
430
data ["exception" ]["values" ][2 ]["value" ]
429
431
== "Error: def occurred outside of Instance pattern"
430
432
)
431
433
432
434
assert data ["exception" ]["values" ][3 ]["type" ] == "IOException"
433
- # Values remain unchanged
434
435
assert (
435
436
data ["exception" ]["values" ][3 ]["value" ]
436
- == "Instance of 'xyz ' and Instance of 'ghi ' both occurred"
437
+ == "Instance of 'NetworkException ' and Instance of 'IOException ' both occurred"
437
438
)
438
439
439
440
@@ -480,21 +481,66 @@ def test_deobfuscate_exception_type_special_regex_chars() -> None:
480
481
):
481
482
deobfuscate_exception_type (data )
482
483
483
- # Exception types deobfuscated, values remain unchanged
484
+ # Exception types deobfuscated; values with the pattern are updated
484
485
assert data ["exception" ]["values" ][0 ]["type" ] == "NetworkException"
485
- assert data ["exception" ]["values" ][0 ]["value" ] == "Instance of 'a.b '"
486
+ assert data ["exception" ]["values" ][0 ]["value" ] == "Instance of 'NetworkException '"
486
487
487
488
assert data ["exception" ]["values" ][1 ]["type" ] == "MathException"
488
- assert data ["exception" ]["values" ][1 ]["value" ] == "Instance of 'x+y ' occurred"
489
+ assert data ["exception" ]["values" ][1 ]["value" ] == "Instance of 'MathException ' occurred"
489
490
490
491
assert data ["exception" ]["values" ][2 ]["type" ] == "ArrayException"
491
- # Values remain unchanged
492
492
assert (
493
493
data ["exception" ]["values" ][2 ]["value" ]
494
- == "Instance of 'test[0] ' and Instance of 'other' patterns"
494
+ == "Instance of 'ArrayException ' and Instance of 'other' patterns"
495
495
)
496
496
497
497
498
+ def test_deobfuscate_exception_value_without_type () -> None :
499
+ """Values should be deobfuscated even if the exception type is missing or None."""
500
+ mock_project = mock .Mock (id = 123 )
501
+
502
+ data : dict [str , Any ] = {
503
+ "project" : 123 ,
504
+ "debug_meta" : {"images" : [{"debug_id" : "test-debug-id" }]},
505
+ "exception" : {
506
+ "values" : [
507
+ {"type" : None , "value" : "Instance of 'xyz'" },
508
+ {"value" : "Unhandled Exception: Instance of 'xyz' was thrown" },
509
+ {"type" : None , "value" : "No pattern here" },
510
+ ]
511
+ },
512
+ }
513
+
514
+ mock_map = {"xyz" : "NetworkException" }
515
+
516
+ with (
517
+ mock .patch (
518
+ "sentry.models.Project.objects.get_from_cache" ,
519
+ return_value = mock_project ,
520
+ ),
521
+ mock .patch (
522
+ "sentry.lang.dart.utils.generate_dart_symbols_map" ,
523
+ return_value = mock_map ,
524
+ ),
525
+ ):
526
+ deobfuscate_exception_type (data )
527
+
528
+ # First: type is None, value should be deobfuscated, type remains None
529
+ assert data ["exception" ]["values" ][0 ]["type" ] is None
530
+ assert data ["exception" ]["values" ][0 ]["value" ] == "Instance of 'NetworkException'"
531
+
532
+ # Second: type key missing, value should be deobfuscated
533
+ assert (
534
+ data ["exception" ]["values" ][1 ]["value" ]
535
+ == "Unhandled Exception: Instance of 'NetworkException' was thrown"
536
+ )
537
+ assert "type" not in data ["exception" ]["values" ][1 ]
538
+
539
+ # Third: no pattern; unchanged
540
+ assert data ["exception" ]["values" ][2 ]["type" ] is None
541
+ assert data ["exception" ]["values" ][2 ]["value" ] == "No pattern here"
542
+
543
+
498
544
# @mock.patch("sentry.lang.dart.utils.generate_dart_symbols_map", return_value=MOCK_DEBUG_MAP)
499
545
# @mock.patch("sentry.lang.dart.utils.get_debug_meta_image_ids", return_value=["test-uuid"])
500
546
# def test_view_hierarchy_deobfuscation(
0 commit comments