Repository: getsentry/sentry

Issue:
Invalid location in source map: (None, None)
![image](https://user-images.githubusercontent.com/2153/28955294-8a24654a-789a-11e7-8b52-12a81a460b85.png)

Seems to occur from an error that points to an HTML document (not a JS file), with no line or column information.

Error:

```json
{
    "errors": [
        {
            "column": null,
            "source": "https://example.com/html/",
            "type": "js_invalid_sourcemap_location",
            "row": null
        }
    ]
}
```

Input stacktrace – no column, line information:

```json
{
    "frames": [
        {
            "abs_path": "https://example.com/html/",
            "in_app": false,
            "module": "<unknown module>",
            "filename": "/html/"
        }
    ]
}
```

Likely triggered [here](https://github.com/getsentry/sentry/blob/master/src/sentry/lang/javascript/processor.py#L653), since there's even comments that suggest line/column information could be missing.

@getsentry/platform 


Discussion:
@mitsuhiko – I took a stab at implementing a fix, but I got buried in the source map processors. It wasn't clear to me how to write an end-to-end test that didn't require mocking out a ton of components. Would really appreciate your help here.
@benvinegar Is there any way so that we can suppress or hide these kind of errors ? I get this error `There were 3 errors encountered while processing this event`. But I want to hide these errors as it is working as expected for me. 
@Tibingeo not yet

Resolving patch:
diff --git a/src/sentry/lang/javascript/processor.py b/src/sentry/lang/javascript/processor.py
--- a/src/sentry/lang/javascript/processor.py
+++ b/src/sentry/lang/javascript/processor.py
@@ -515,8 +515,8 @@ def process_frame(self, processable_frame, processing_task):
         all_errors = []
         sourcemap_applied = False
 
-        # can't fetch source if there's no filename present
-        if not frame.get('abs_path'):
+        # can't fetch source if there's no filename present or no line
+        if not frame.get('abs_path') or not frame.get('lineno'):
             return
 
         errors = cache.get_errors(frame['abs_path'])
@@ -650,14 +650,16 @@ def process_frame(self, processable_frame, processing_task):
         # another mapped, minified source
         changed_frame = self.expand_frame(new_frame, source=source)
 
-        if not new_frame.get('context_line') and source:
+        # If we did not manage to match but we do have a line or column
+        # we want to report an error here.
+        if not new_frame.get('context_line') \
+           and source and \
+           new_frame.get('colno') is not None:
             all_errors.append(
                 {
                     'type': EventError.JS_INVALID_SOURCEMAP_LOCATION,
-                    # Column might be missing here
-                    'column': new_frame.get('colno'),
-                    # Line might be missing here
-                    'row': new_frame.get('lineno'),
+                    'column': new_frame['colno'],
+                    'row': new_frame['lineno'],
                     'source': new_frame['abs_path'],
                 }
             )


Test patch:
diff --git a/tests/sentry/lang/javascript/test_plugin.py b/tests/sentry/lang/javascript/test_plugin.py
--- a/tests/sentry/lang/javascript/test_plugin.py
+++ b/tests/sentry/lang/javascript/test_plugin.py
@@ -967,6 +967,50 @@ def test_failed_sourcemap_expansion_data_url(self):
         event = Event.objects.get()
         assert event.data['errors'] == [{'url': u'<data url>', 'type': 'js_no_source'}]
 
+    @responses.activate
+    def test_failed_sourcemap_expansion_missing_location_entirely(self):
+        responses.add(
+            responses.GET,
+            'http://example.com/indexed.min.js',
+            body='//# sourceMappingURL=indexed.sourcemap.js',
+        )
+        responses.add(
+            responses.GET,
+            'http://example.com/indexed.sourcemap.js',
+            body='{}'
+        )
+        data = {
+            'message': 'hello',
+            'platform': 'javascript',
+            'sentry.interfaces.Exception': {
+                'values': [
+                    {
+                        'type': 'Error',
+                        'stacktrace': {
+                            'frames': [
+                                {
+                                    'abs_path': 'http://example.com/indexed.min.js',
+                                    'filename': 'indexed.min.js',
+                                    'lineno': 1,
+                                    'colno': 1,
+                                },
+                                {
+                                    'abs_path': 'http://example.com/indexed.min.js',
+                                    'filename': 'indexed.min.js',
+                                },
+                            ],
+                        },
+                    }
+                ],
+            }
+        }
+
+        resp = self._postWithHeader(data)
+        assert resp.status_code == 200
+
+        event = Event.objects.get()
+        assert event.data['errors'] == []
+
     @responses.activate
     def test_html_response_for_js(self):
         responses.add(