Repository: great-expectations/great_expectations

Issue:
Error in slack_notification Action
Hi Guys,
I have 3 pipelines with great expectations, but one pipeline started to give some errors:

`Error running action with name notify_slack
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/validation_operators.py", line 384, in _run_actions
    payload=batch_actions_results,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/actions.py", line 55, in run
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/actions.py", line 170, in _run
    validation_result_suite, data_docs_pages, self.notify_with
  File "/usr/local/lib/python3.7/site-packages/great_expectations/render/renderer/slack_renderer.py", line 101, in render
    report_element = self._get_report_element(docs_link)
  File "/usr/local/lib/python3.7/site-packages/great_expectations/render/renderer/slack_renderer.py", line 155, in _get_report_element
    if "file:///" in docs_link:
TypeError: argument of type 'NoneType' is not iterable
Traceback (most recent call last):
  File "fact_demand_coverage_datalake_datasets_job.py", line 90, in <module>
    expectation_suite=expectation_suite_name_for_validations
  File "/mnt1/yarn/usercache/hadoop/appcache/application_1603978914184_5458/container_1603978914184_5458_01_000001/data_quality.zip/data_quality/ge_validation.py", line 174, in validate
  File "/usr/local/lib/python3.7/site-packages/great_expectations/core/usage_statistics/usage_statistics.py", line 257, in usage_statistics_wrapped_method
    result = func(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/great_expectations/data_context/data_context.py", line 1022, in run_validation_operator
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/validation_operators.py", line 334, in run
    run_id,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/validation_operators.py", line 399, in _run_actions
    raise e
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/validation_operators.py", line 384, in _run_actions
    payload=batch_actions_results,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/actions.py", line 55, in run
    **kwargs,
  File "/usr/local/lib/python3.7/site-packages/great_expectations/validation_operators/actions.py", line 170, in _run
    validation_result_suite, data_docs_pages, self.notify_with
  File "/usr/local/lib/python3.7/site-packages/great_expectations/render/renderer/slack_renderer.py", line 101, in render
    report_element = self._get_report_element(docs_link)
  File "/usr/local/lib/python3.7/site-packages/great_expectations/render/renderer/slack_renderer.py", line 155, in _get_report_element
    if "file:///" in docs_link:
TypeError: argument of type 'NoneType' is not iterable`

The stranger thing with this error, the error doesn't happen every day, for example yesterday it worked fine.


Discussion:
I'm running GE on spark.
Thank you for reporting this, @rubenssoto ! We will triage today.
I don't know, may be related to the problem that I showed you on data docs.
Acknowledging this as a bug - the core team will provide a fix.

Resolving patch:
diff --git a/great_expectations/render/renderer/slack_renderer.py b/great_expectations/render/renderer/slack_renderer.py
--- a/great_expectations/render/renderer/slack_renderer.py
+++ b/great_expectations/render/renderer/slack_renderer.py
@@ -116,10 +116,6 @@ def render(
                 }
                 query["blocks"].append(dataset_element)
 
-        custom_blocks = self._custom_blocks(evr=validation_result)
-        if custom_blocks:
-            query["blocks"].append(custom_blocks)
-
         documentation_url = "https://docs.greatexpectations.io/en/latest/guides/tutorials/getting_started/set_up_data_docs.html"
         footer_section = {
             "type": "context",
@@ -136,29 +132,36 @@ def render(
         query["blocks"].append(footer_section)
         return query
 
-    def _custom_blocks(self, evr):
-        return None
-
     def _get_report_element(self, docs_link):
-        if docs_link is None:
-            logger.warn("No docs link found. Skipping data docs link in slack message.")
-            return
-
-        if "file://" in docs_link:
-            # handle special case since Slack does not render these links
-            report_element = {
-                "type": "section",
-                "text": {
-                    "type": "mrkdwn",
-                    "text": f"*DataDocs* can be found here: `{docs_link}` \n (Please copy and paste link into a browser to view)\n",
-                },
-            }
+        report_element = None
+        if docs_link:
+            try:
+                if "file://" in docs_link:
+                    # handle special case since Slack does not render these links
+                    report_element = {
+                        "type": "section",
+                        "text": {
+                            "type": "mrkdwn",
+                            "text": f"*DataDocs* can be found here: `{docs_link}` \n (Please copy and paste link into a browser to view)\n",
+                        },
+                    }
+                else:
+                    report_element = {
+                        "type": "section",
+                        "text": {
+                            "type": "mrkdwn",
+                            "text": f"*DataDocs* can be found here: <{docs_link}|{docs_link}>",
+                        },
+                    }
+            except Exception as e:
+                logger.warning(
+                    f"""SlackRenderer had a problem with generating the docs link.
+                    link used to generate the docs link is: {docs_link} and is of type: {type(docs_link)}.
+                    Error: {e}"""
+                )
+                return
         else:
-            report_element = {
-                "type": "section",
-                "text": {
-                    "type": "mrkdwn",
-                    "text": f"*DataDocs* can be found here: <{docs_link}|{docs_link}>",
-                },
-            }
+            logger.warning(
+                "No docs link found. Skipping data docs link in Slack message."
+            )
         return report_element


Test patch:
diff --git a/tests/render/test_SlackRenderer.py b/tests/render/test_SlackRenderer.py
--- a/tests/render/test_SlackRenderer.py
+++ b/tests/render/test_SlackRenderer.py
@@ -1,11 +1,7 @@
-# from freezegun import freeze_time
-import pytest
-
 from great_expectations.core.expectation_validation_result import (
     ExpectationSuiteValidationResult,
 )
 from great_expectations.render.renderer import SlackRenderer
-from tests.test_utils import modify_locale
 
 
 def test_SlackRenderer_validation_results_with_datadocs():
@@ -134,3 +130,15 @@ def test_SlackRenderer_validation_results_with_datadocs():
     }
 
     assert rendered_output == expected_output
+
+
+def test_SlackRenderer_get_report_element():
+    slack_renderer = SlackRenderer()
+
+    # these should all be caught
+    assert slack_renderer._get_report_element(docs_link=None) is None
+    assert slack_renderer._get_report_element(docs_link=1) is None
+    assert slack_renderer._get_report_element(docs_link=slack_renderer) is None
+
+    # this should work
+    assert slack_renderer._get_report_element(docs_link="i_should_work") is not None