diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
index 449996710eb60a9fa54d933801b7f2b713e9105d..90513008f30219138ed90ba14e66e7f3c283a3f8 100644
--- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
+++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Core\TypedData\Validation;
 
+use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
 use Drupal\Core\TypedData\ComplexDataInterface;
 use Drupal\Core\TypedData\ListInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
@@ -136,6 +137,7 @@ protected function validateNode(TypedDataInterface $data, $constraints = NULL, $
     // constraint validators, such that they do not have to care about Typed
     // Data.
     $value = $typed_data_manager->getCanonicalRepresentation($data);
+    $constraints_given = isset($constraints);
     $this->context->setNode($value, $data, $metadata, $property_path);
 
     if (isset($constraints) || !$this->context->isGroupValidated($cache_key, Constraint::DEFAULT_GROUP)) {
@@ -148,7 +150,10 @@ protected function validateNode(TypedDataInterface $data, $constraints = NULL, $
 
     // 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.
-    if (($data instanceof ListInterface || $data instanceof ComplexDataInterface) && !$data->isEmpty()) {
+    // Next, we do not recurse if given constraints are validated against an
+    // entity, since we should determine whether the entity matches the
+    // constraints and not whether the entity validates.
+    if (($data instanceof ListInterface || $data instanceof ComplexDataInterface) && !$data->isEmpty() && !($data instanceof EntityAdapter && $constraints_given)) {
       foreach ($data as $name => $property) {
         $this->validateNode($property);
       }
diff --git a/core/tests/Drupal/KernelTests/Core/TypedData/RecursiveContextualValidatorTest.php b/core/tests/Drupal/KernelTests/Core/TypedData/RecursiveContextualValidatorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f60b399073808298eae04df2d27be20e8cbc4315
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/TypedData/RecursiveContextualValidatorTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Drupal\KernelTests\Core\TypedData;
+
+use Drupal\Core\Entity\Plugin\DataType\EntityAdapter;
+use Drupal\entity_test\Entity\EntityTest;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * @coversDefaultClass \Drupal\Core\TypedData\Validation\RecursiveContextualValidator
+ * @group Validation
+ */
+class RecursiveContextualValidatorTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'entity_test',
+    'user',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('entity_test');
+  }
+
+  /**
+   * Tests recursive validation against given constraints against an entity.
+   */
+  public function testRecursiveValidate() {
+    $entity = EntityTest::create();
+    $adapter = EntityAdapter::createFromEntity($entity);
+    // This would trigger the ValidReferenceConstraint due to EntityTest
+    // defaulting uid to 1, which doesn't exist. Ensure that we don't get a
+    // violation for that.
+    $this->assertCount(0, \Drupal::typedDataManager()->getValidator()->validate($adapter, $adapter->getConstraints()));
+  }
+
+}