Browse Source

fix(react): Make React error matching regex more lenient (#71008)

The regex that matches React error messages currently enforces the
existence of a query string in the URL. We have seen error messages
without query strings in the wild, which causes those errors to not be
unminified.

This makes the regex more lenient by making the query part optional: the
query part `\?(\S+)` is wrapped in `(?:…)?` to make it optional without
creating an additional capture group, giving `(?:\?(\S+))?`.
Sebastian Zivota 10 months ago
parent
commit
9f09d343ad

+ 7 - 1
src/sentry/lang/javascript/errormapping.py

@@ -25,6 +25,12 @@ REACT_MAPPING_URL = (
     "https://raw.githubusercontent.com/facebook/react/master/scripts/error-codes/codes.json"
 )
 
+# Regex for React error messages.
+# * The `(\d+)` group matches the error code
+# * The `(?:\?(\S+))?` group optionally matches a query (non-capturing),
+#   and `(\S+)` matches the query parameters.
+REACT_ERROR_REGEX = r"Minified React error #(\d+); visit https?://[^?]+(?:\?(\S+))?"
+
 error_processors: dict[str, Processor] = {}
 
 
@@ -85,7 +91,7 @@ def minified_error(vendor, mapping_url, regex):
 @minified_error(
     vendor="react",
     mapping_url=REACT_MAPPING_URL,
-    regex=r"Minified React error #(\d+); visit https?://[^?]+\?(\S+)",
+    regex=REACT_ERROR_REGEX,
 )
 def process_react_exception(exc, match, mapping):
     error_id, qs = match.groups()

+ 36 - 0
tests/sentry/lang/javascript/test_errormapping.py

@@ -68,6 +68,42 @@ class ErrorMappingTest(unittest.TestCase):
                 "some other invalid object."
             )
 
+    @responses.activate
+    def test_react_error_mapping_resolving_no_query(self):
+        responses.add(
+            responses.GET,
+            REACT_MAPPING_URL,
+            body=r"""
+        {
+            "425": "Text content does not match server-rendered HTML."
+        }
+        """,
+            content_type="application/json",
+        )
+
+        data: dict[str, Any] = {
+            "platform": "javascript",
+            "exception": {
+                "values": [
+                    {
+                        "type": "Error",
+                        "value": (
+                            "Minified React error #425; visit https://react.dev/errors/425"
+                            "for the full message or use the non-minified dev environment"
+                            "for full errors and additional helpful warnings."
+                        ),
+                    }
+                ]
+            },
+        }
+
+        assert rewrite_exception(data)
+
+        assert (
+            data["exception"]["values"][0]["value"]
+            == "Text content does not match server-rendered HTML."
+        )
+
     @responses.activate
     def test_react_error_mapping_empty_args(self):
         responses.add(