diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
index a5d453ae58..28222c47c9 100644
--- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
+++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
@@ -132,21 +132,26 @@ protected function validateNode(TypedDataInterface $data, $constraints = NULL, $
     $value = $this->typedDataManager->getCanonicalRepresentation($data);
     $this->context->setNode($value, $data, $metadata, $property_path);
 
-    if (isset($constraints) || !$this->context->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP)) {
-      if (!isset($constraints)) {
-        $this->context->markGroupAsValidated($cache_key, Constraint::DEFAULT_GROUP);
-        $constraints = $metadata->findConstraints(Constraint::DEFAULT_GROUP);
-      }
-      $this->validateConstraints($value, $cache_key, $constraints);
-    }
-
     // If the data is a list or complex data, validate the contained list items
     // or properties. However, do not recurse if the data is empty.
+    $count_violations_before = count($this->context->getViolations());
     if (($data instanceof ListInterface || $data instanceof ComplexDataInterface) && !$data->isEmpty()) {
       foreach ($data as $name => $property) {
         $this->validateNode($property);
       }
     }
+    $count_violations_after = count($this->context->getViolations());
+
+    // Don't validate the current level if there has been any violations on the
+    // deeper levels, as the current level might require for example the
+    // existence of some values.
+    if (($count_violations_after === $count_violations_before) && (isset($constraints) || !$this->context->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP))) {
+      if (!isset($constraints)) {
+        $this->context->markGroupAsValidated($cache_key, Constraint::DEFAULT_GROUP);
+        $constraints = $metadata->findConstraints(Constraint::DEFAULT_GROUP);
+      }
+      $this->validateConstraints($value, $cache_key, $constraints);
+    }
 
     $this->context->setNode($previous_value, $previous_object, $previous_metadata, $previous_path);
 
diff --git a/core/modules/comment/src/Entity/Comment.php b/core/modules/comment/src/Entity/Comment.php
index 821b30d0ba..3eeb7d5557 100644
--- a/core/modules/comment/src/Entity/Comment.php
+++ b/core/modules/comment/src/Entity/Comment.php
@@ -310,6 +310,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
     $fields['entity_type'] = BaseFieldDefinition::create('string')
       ->setLabel(t('Entity type'))
       ->setDescription(t('The entity type to which this comment is attached.'))
+      ->setRequired(TRUE)
       ->setSetting('is_ascii', TRUE)
       ->setSetting('max_length', EntityTypeInterface::ID_MAX_LENGTH);
 
diff --git a/core/modules/comment/src/Plugin/Validation/Constraint/CommentNameConstraintValidator.php b/core/modules/comment/src/Plugin/Validation/Constraint/CommentNameConstraintValidator.php
index 87cdaf91de..8ca89a1805 100644
--- a/core/modules/comment/src/Plugin/Validation/Constraint/CommentNameConstraintValidator.php
+++ b/core/modules/comment/src/Plugin/Validation/Constraint/CommentNameConstraintValidator.php
@@ -52,6 +52,12 @@ public function validate($entity, Constraint $constraint) {
     $author_name = $entity->name->value;
     $owner_id = (int) $entity->uid->target_id;
 
+    // Return early if no entity_id is set; without it, we can't perform an
+    // @todo this actually even requires a VALID entity ID & comment field name. So this is not sufficient yet!
+    if ($entity->entity_id->value === NULL && $entity->field_name->value) {
+      return;
+    }
+
     // Do not allow unauthenticated comment authors to use a name that is
     // taken by a registered user.
     if (isset($author_name) && $author_name !== '' && $owner_id === 0) {
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
index ea705de8a4..932dbfcb3f 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
@@ -275,27 +275,12 @@ public function testPostDxWithoutCriticalBaseFields() {
     // DX: 422 when missing 'entity_type' field.
     $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_type' => TRUE]), static::$format);
     $response = $this->request('POST', $url, $request_options);
-    // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
-    $this->assertSame(500, $response->getStatusCode());
-    $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
-    $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.</br></br><em class="placeholder">Symfony\Component\HttpKernel\Exception\HttpException</em>: Internal Server Error in <em class="placeholder">Drupal\rest\Plugin\rest\resource\EntityResource-&gt;post()</em>', (string) $response->getBody());
-    //$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
 
     // DX: 422 when missing 'entity_id' field.
     $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['entity_id' => TRUE]), static::$format);
-    // @todo Remove the try/catch in favor of the two commented lines in
-    // https://www.drupal.org/node/2820364.
-    try {
-      $response = $this->request('POST', $url, $request_options);
-      // This happens on DrupalCI.
-      //$this->assertSame(500, $response->getStatusCode());
-    }
-    catch (\Exception $e) {
-      // This happens on Wim's local machine.
-      //$this->assertSame("Error: Call to a member function get() on null\nDrupal\\comment\\Plugin\\Validation\\Constraint\\CommentNameConstraintValidator->getAnonymousContactDetailsSetting()() (Line: 96)\n", $e->getMessage());
-    }
-    //$response = $this->request('POST', $url, $request_options);
-    //$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
+    $response = $this->request('POST', $url, $request_options);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_id: This value should not be null.\n", $response);
 
     // DX: 422 when missing 'entity_type' field.
     $request_options[RequestOptions::BODY] = $this->serializer->encode(array_diff_key($this->getNormalizedPostEntity(), ['field_name' => TRUE]), static::$format);
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
index caf2909762..f0624c99cd 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/User/UserResourceTestBase.php
@@ -162,7 +162,7 @@ public function testPatchDxForSecuritySensitiveBaseFields() {
 
     // DX: 422 when changing email without providing the password.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
+    $this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\npass: Your current password is missing or incorrect; it's required to change the Password.\nmail: Your current password is missing or incorrect; it's required to change the Email.\n", $response);
 
 
     $normalization['pass'] = [['existing' => 'wrong']];
diff --git a/core/tests/Drupal/Tests/Core/TypedData/RecursiveContextualValidatorTest.php b/core/tests/Drupal/Tests/Core/TypedData/RecursiveContextualValidatorTest.php
index 08b8117034..a702b86c2b 100644
--- a/core/tests/Drupal/Tests/Core/TypedData/RecursiveContextualValidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/TypedData/RecursiveContextualValidatorTest.php
@@ -166,21 +166,17 @@ public function testPropertiesValidateWithMultipleLevels() {
     $typed_data = $this->buildExampleTypedDataWithProperties();
 
     $violations = $this->recursiveValidator->validate($typed_data);
-    $this->assertCount(6, $violations);
-
-    $this->assertEquals('violation: 3', $violations->get(0)->getMessage());
-    $this->assertEquals('violation: value1', $violations->get(1)->getMessage());
-    $this->assertEquals('violation: value2', $violations->get(2)->getMessage());
-    $this->assertEquals('violation: 2', $violations->get(3)->getMessage());
-    $this->assertEquals('violation: subvalue1', $violations->get(4)->getMessage());
-    $this->assertEquals('violation: subvalue2', $violations->get(5)->getMessage());
-
-    $this->assertEquals('', $violations->get(0)->getPropertyPath());
-    $this->assertEquals('key1', $violations->get(1)->getPropertyPath());
-    $this->assertEquals('key2', $violations->get(2)->getPropertyPath());
-    $this->assertEquals('key_with_properties', $violations->get(3)->getPropertyPath());
-    $this->assertEquals('key_with_properties.subkey1', $violations->get(4)->getPropertyPath());
-    $this->assertEquals('key_with_properties.subkey2', $violations->get(5)->getPropertyPath());
+    $this->assertCount(4, $violations);
+
+    $this->assertEquals('violation: value1', $violations->get(0)->getMessage());
+    $this->assertEquals('violation: value2', $violations->get(1)->getMessage());
+    $this->assertEquals('violation: subvalue1', $violations->get(2)->getMessage());
+    $this->assertEquals('violation: subvalue2', $violations->get(3)->getMessage());
+
+    $this->assertEquals('key1', $violations->get(0)->getPropertyPath());
+    $this->assertEquals('key2', $violations->get(1)->getPropertyPath());
+    $this->assertEquals('key_with_properties.subkey1', $violations->get(2)->getPropertyPath());
+    $this->assertEquals('key_with_properties.subkey2', $violations->get(3)->getPropertyPath());
   }
 
   /**
@@ -270,15 +266,13 @@ public function testValidateProperty() {
     $typed_data = $this->buildExampleTypedDataWithProperties();
 
     $violations = $this->recursiveValidator->validateProperty($typed_data, 'key_with_properties');
-    $this->assertCount(3, $violations);
+    $this->assertCount(2, $violations);
 
-    $this->assertEquals('violation: 2', $violations->get(0)->getMessage());
-    $this->assertEquals('violation: subvalue1', $violations->get(1)->getMessage());
-    $this->assertEquals('violation: subvalue2', $violations->get(2)->getMessage());
+    $this->assertEquals('violation: subvalue1', $violations->get(0)->getMessage());
+    $this->assertEquals('violation: subvalue2', $violations->get(1)->getMessage());
 
-    $this->assertEquals('', $violations->get(0)->getPropertyPath());
-    $this->assertEquals('subkey1', $violations->get(1)->getPropertyPath());
-    $this->assertEquals('subkey2', $violations->get(2)->getPropertyPath());
+    $this->assertEquals('subkey1', $violations->get(0)->getPropertyPath());
+    $this->assertEquals('subkey2', $violations->get(1)->getPropertyPath());
   }
 
   /**
@@ -298,15 +292,13 @@ public function testValidatePropertyValue() {
     $typed_data = $this->buildExampleTypedDataWithProperties(['subkey1' => 'subvalue11', 'subkey2' => 'subvalue22']);
 
     $violations = $this->recursiveValidator->validatePropertyValue($typed_data, 'key_with_properties', $typed_data->get('key_with_properties'));
-    $this->assertCount(3, $violations);
+    $this->assertCount(2, $violations);
 
-    $this->assertEquals('violation: 2', $violations->get(0)->getMessage());
-    $this->assertEquals('violation: subvalue11', $violations->get(1)->getMessage());
-    $this->assertEquals('violation: subvalue22', $violations->get(2)->getMessage());
+    $this->assertEquals('violation: subvalue11', $violations->get(0)->getMessage());
+    $this->assertEquals('violation: subvalue22', $violations->get(1)->getMessage());
 
-    $this->assertEquals('', $violations->get(0)->getPropertyPath());
-    $this->assertEquals('subkey1', $violations->get(1)->getPropertyPath());
-    $this->assertEquals('subkey2', $violations->get(2)->getPropertyPath());
+    $this->assertEquals('subkey1', $violations->get(0)->getPropertyPath());
+    $this->assertEquals('subkey2', $violations->get(1)->getPropertyPath());
   }
 
   /**
