Repository: great-expectations/great_expectations

Issue:
Renderer fails to serialize results when exceptions occurs during validation
**Describe the bug**
If validation throws an exception, then renderer fails to render results with the following error:

```
Failed to validate tables. Error: {'results': {0: {'expectation_config': ['Field may not be null.']}}}
```

**To Reproduce**
Steps to reproduce the behavior:
1. Run checkpoint with a suite that contains `expect_column_most_common_value_to_be_in_set` expectation with sqlalchemy engine (which is not supported)
2. See error
``` great_expectations\data_context\data_context.py", line 2375, in build_data_docs
    index_page_resource_identifier_tuple = site_builder.build(
   great_expectations\render\renderer\site_builder.py", line 293, in build
    site_section_builder.build(resource_identifiers=resource_identifiers)
   great_expectations\render\renderer\site_builder.py", line 409, in build
    resource = self.source_store.get(resource_key)
   great_expectations\data_context\store\store.py", line 123, in get
    return self.deserialize(key, value)
   great_expectations\data_context\store\validations_store.py", line 152, in deserialize
    return self._expectationSuiteValidationResultSchema.loads(value)
   great_expectations\marshmallow__shade\schema.py", line 769, in loads
    return self.load(data, many=many, partial=partial, unknown=unknown)
   great_expectations\marshmallow__shade\schema.py", line 735, in load
    return self._do_load(
   great_expectations\marshmallow__shade\schema.py", line 917, in _do_load
    raise exc
great_expectations.marshmallow__shade.exceptions.ValidationError: {'results': {0: {'expectation_config': ['Field may not be null.']}}}
```

**Expected behavior**
The error is properly rendered in datadocs

**Environment (please complete the following information):**
 - Operating System:  Windows
 - Great Expectations Version:  0.13.19

**Additional context**
Add any other context about the problem here.



Discussion:

Resolving patch:
diff --git a/great_expectations/validator/validator.py b/great_expectations/validator/validator.py
--- a/great_expectations/validator/validator.py
+++ b/great_expectations/validator/validator.py
@@ -459,6 +459,7 @@ def graph_validate(
                             "exception_traceback": exception_traceback,
                             "exception_message": str(err),
                         },
+                        expectation_config=configuration,
                     )
                     evrs.append(result)
                 else:
@@ -488,6 +489,7 @@ def graph_validate(
                             "exception_traceback": exception_traceback,
                             "exception_message": str(err),
                         },
+                        expectation_config=configuration,
                     )
                     evrs.append(result)
                 else:


Test patch:
diff --git a/tests/validator/test_validator.py b/tests/validator/test_validator.py
--- a/tests/validator/test_validator.py
+++ b/tests/validator/test_validator.py
@@ -234,7 +234,49 @@ def test_graph_validate(basic_datasource):
     ]
 
 
-# this might indicate that we need to validate configuration a little more strictly prior to actually validating
+def test_graph_validate_with_exception(basic_datasource):
+    def mock_error(*args, **kwargs):
+        raise Exception("Mock Error")
+
+    df = pd.DataFrame({"a": [1, 5, 22, 3, 5, 10], "b": [1, 2, 3, 4, 5, None]})
+
+    batch = basic_datasource.get_single_batch_from_batch_request(
+        RuntimeBatchRequest(
+            **{
+                "datasource_name": "my_datasource",
+                "data_connector_name": "test_runtime_data_connector",
+                "data_asset_name": "IN_MEMORY_DATA_ASSET",
+                "runtime_parameters": {
+                    "batch_data": df,
+                },
+                "batch_identifiers": {
+                    "pipeline_stage_name": 0,
+                    "airflow_run_id": 0,
+                    "custom_key_0": 0,
+                },
+            }
+        )
+    )
+
+    expectation_configuration = ExpectationConfiguration(
+        expectation_type="expect_column_value_z_scores_to_be_less_than",
+        kwargs={
+            "column": "b",
+            "mostly": 0.9,
+            "threshold": 4,
+            "double_sided": True,
+        },
+    )
+
+    validator = Validator(execution_engine=PandasExecutionEngine(), batches=[batch])
+    validator.build_metric_dependency_graph = mock_error
+
+    result = validator.graph_validate(configurations=[expectation_configuration])
+
+    assert len(result) == 1
+    assert result[0].expectation_config is not None
+
+
 def test_graph_validate_with_bad_config(basic_datasource):
     df = pd.DataFrame({"a": [1, 5, 22, 3, 5, 10], "b": [1, 2, 3, 4, 5, None]})