diff --git a/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionInterface.php b/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionInterface.php
index 864e717..f240c19 100644
--- a/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionInterface.php
@@ -49,6 +49,20 @@ public function countReferenceableEntities($match = NULL, $match_operator = 'CON
   public function validateReferenceableEntities(array $ids);
 
   /**
+   * Validates that entities can be referenced by this field.
+   *
+   * @todo naming...
+   *
+   * @param \Drupal\Core\Entity\EntityInterface[] $entities
+   *   An array of entities to check.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface[]
+   *   The incoming $entities parameter, filtered for valid entities. Array keys
+   *   are preserved.
+   */
+  public function validateReferenceableNewEntities(array $entities);
+
+  /**
    * Validates input from an autocomplete widget that has no ID.
    *
    * @param string $input
diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
index c67dc68..33ffc07 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
@@ -271,6 +271,18 @@ public function validateReferenceableEntities(array $ids) {
   /**
    * {@inheritdoc}
    */
+  public function validateReferenceableNewEntities(array $entities) {
+    return array_filter($entities, function ($entity) {
+      if (isset($this->configuration['handler_settings']['target_bundles'])) {
+        return in_array($entity->bundle(), $this->configuration['handler_settings']['target_bundles']);
+      }
+      return TRUE;
+    });
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function validateAutocompleteInput($input, &$element, FormStateInterface $form_state, $form, $strict = TRUE) {
     $bundled_entities = $this->getReferenceableEntities($input, '=', 6);
     $entities = array();
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraint.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraint.php
index bf8658a..79cf120 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraint.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraint.php
@@ -26,7 +26,7 @@ class ValidReferenceConstraint extends Constraint {
    *
    * @var string
    */
-  public $message = 'The referenced entity (%type: %id) does not exist.';
+  public $message = 'This entity (%type: %id) cannot be referenced.';
 
   /**
    * Validation message when the target_id is empty.
diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
index 8f704c1..cfcdd85 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php
@@ -19,27 +19,68 @@ class ValidReferenceConstraintValidator extends ConstraintValidator {
    * {@inheritdoc}
    */
   public function validate($value, Constraint $constraint) {
-    /** @var \Drupal\Core\Field\FieldItemInterface $value */
+    /** @var \Drupal\Core\Field\FieldItemListInterface $value */
     /** @var ValidReferenceConstraint $constraint */
     if (!isset($value)) {
       return;
     }
-    // We don't use a regular NotNull constraint for the target_id property as
-    // a NULL value is valid if the entity property contains an unsaved entity.
-    // @see \Drupal\Core\TypedData\DataReferenceTargetDefinition::getConstraints
-    if (!$value->isEmpty() && $value->target_id === NULL && !$value->entity->isNew()) {
-      $this->context->addViolation($constraint->nullMessage);
-      return;
+
+    // Collect new entities and IDs of existing entities across the field items.
+    $new_entities = [];
+    $target_ids = [];
+    foreach ($value as $delta => $item) {
+      $target_id = $item->target_id;
+      // We don't use a regular NotNull constraint for the target_id property as
+      // NULL is allowed if the entity property contains an unsaved entity.
+      // @see \Drupal\Core\TypedData\DataReferenceTargetDefinition::getConstraints()
+      if (!$item->isEmpty() && $target_id === NULL) {
+        if (!$item->entity->isNew()) {
+          $this->context->buildViolation($constraint->nullMessage)
+            ->atPath((string) $delta)
+            ->addViolation();
+          return;
+        }
+        $new_entities[$delta] = $item->entity;
+      }
+
+      // '0' or NULL are considered valid empty references.
+      if (!empty($target_id)) {
+        $target_ids[$delta] = $target_id;
+      }
     }
-    $id = $value->get('target_id')->getValue();
-    // '0' or NULL are considered valid empty references.
-    if (empty($id)) {
-      return;
-    }
-    $referenced_entity = $value->get('entity')->getValue();
-    if (!$referenced_entity) {
-      $type = $value->getFieldDefinition()->getSetting('target_type');
-      $this->context->addViolation($constraint->message, array('%type' => $type, '%id' => $id));
+
+    if ($new_entities || $target_ids) {
+      /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler * */
+      $handler = \Drupal::service('plugin.manager.entity_reference_selection')->getSelectionHandler($value->getFieldDefinition());
+      $target_type = $value->getFieldDefinition()->getSetting('target_type');
+
+      // Add violations on deltas with a new entity that is not valid.
+      if ($new_entities) {
+        $valid_new_entities = $handler->validateReferenceableNewEntities($new_entities);
+        foreach (array_diff_key($new_entities, $valid_new_entities) as $delta => $entity) {
+          // @todo adjust message
+          $this->context->buildViolation('Invalid new entity')
+            ->setParameter('%type', $target_type)
+            ->atPath((string) $delta . '.entity')
+            ->setInvalidValue($entity)
+            ->addViolation();
+        }
+      }
+
+      // Add violations on deltas with a target_id that is not valid.
+      if ($target_ids) {
+        $valid_target_ids = $handler->validateReferenceableEntities($target_ids);
+        foreach (array_diff($target_ids, $valid_target_ids) as $delta => $target_id) {
+          $this->context->buildViolation($constraint->message)
+            ->setParameter('%type', $target_type)
+            ->setParameter('%id', $target_id)
+            ->atPath((string) $delta . '.target_id')
+            ->setInvalidValue($target_id)
+            ->addViolation();
+        }
+      }
     }
+
   }
+
 }
diff --git a/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php b/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php
index 4217b2e..63587bb 100644
--- a/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php
+++ b/core/lib/Drupal/Core/Field/EntityReferenceFieldItemList.php
@@ -15,6 +15,13 @@
  */
 class EntityReferenceFieldItemList extends FieldItemList implements EntityReferenceFieldItemListInterface {
 
+  public function getConstraints() {
+    $constraints = parent::getConstraints();
+    $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
+    $constraints[] = $constraint_manager->create('ValidReference', []);
+    return $constraints;
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 70397fa..ea0ee73 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -22,9 +22,6 @@
  *
  * Supported settings (below the definition's 'settings' key) are:
  * - target_type: The entity type to reference. Required.
- * - target_bundle: (optional): If set, restricts the entity bundles which may
- *   may be referenced. May be set to an single bundle, or to an array of
- *   allowed bundles.
  *
  * @FieldType(
  *   id = "entity_reference",
@@ -33,8 +30,7 @@
  *   category = @Translation("Reference"),
  *   no_ui = TRUE,
  *   default_formatter = "entity_reference_label",
- *   list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
- *   constraints = {"ValidReference" = {}}
+ *   list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList"
  * )
  */
 class EntityReferenceItem extends FieldItemBase {
@@ -53,7 +49,7 @@ public static function defaultStorageSettings() {
    */
   public static function defaultFieldSettings() {
     return array(
-      'handler' => 'default:' . (\Drupal::moduleHandler()->moduleExists('node') ? 'node' : 'user'),
+      'handler' => 'default',
       'handler_settings' => array(),
     ) + parent::defaultFieldSettings();
   }
@@ -148,28 +144,6 @@ public static function schema(FieldStorageDefinitionInterface $field_definition)
   /**
    * {@inheritdoc}
    */
-  public function getConstraints() {
-    $constraints = parent::getConstraints();
-    list($current_handler) = explode(':', $this->getSetting('handler'), 2);
-    if ($current_handler === 'default') {
-      $handler_settings = $this->getSetting('handler_settings');
-      if (!empty($handler_settings['target_bundles'])) {
-        $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
-        $constraints[] = $constraint_manager->create('ComplexData', [
-          'entity' => [
-            'Bundle' => [
-              'bundle' => $handler_settings['target_bundles'],
-            ],
-          ],
-        ]);
-      }
-    }
-    return $constraints;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function setValue($values, $notify = TRUE) {
     if (isset($values) && !is_array($values)) {
       // If either a scalar or an object was passed as the value for the item,
diff --git a/core/modules/comment/src/Tests/CommentValidationTest.php b/core/modules/comment/src/Tests/CommentValidationTest.php
index 62acec0..5c30d89 100644
--- a/core/modules/comment/src/Tests/CommentValidationTest.php
+++ b/core/modules/comment/src/Tests/CommentValidationTest.php
@@ -39,7 +39,7 @@ protected function setUp() {
    */
   public function testValidation() {
     // Add a user.
-    $user = User::create(array('name' => 'test'));
+    $user = User::create(array('name' => 'test', 'status' => TRUE));
     $user->save();
 
     // Add comment type.
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
index afff2a3..4e2b6db 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
@@ -27,7 +27,7 @@
  *   default_widget = "file_generic",
  *   default_formatter = "file_default",
  *   list_class = "\Drupal\file\Plugin\Field\FieldType\FileFieldItemList",
- *   constraints = {"ValidReference" = {}, "ReferenceAccess" = {}}
+ *   constraints = {"ReferenceAccess" = {}}
  * )
  */
 class FileItem extends EntityReferenceItem {
diff --git a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
index 442929f..35e5004 100644
--- a/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/src/Plugin/Field/FieldType/ImageItem.php
@@ -43,7 +43,7 @@
  *     },
  *   },
  *   list_class = "\Drupal\file\Plugin\Field\FieldType\FileFieldItemList",
- *   constraints = {"ValidReference" = {}, "ReferenceAccess" = {}}
+ *   constraints = {"ReferenceAccess" = {}}
  * )
  */
 class ImageItem extends FileItem {
diff --git a/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php b/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
index 0fdd9af..6cdef4d 100644
--- a/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
+++ b/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
@@ -259,7 +259,7 @@ public function testInvalidEntityAutocompleteElement() {
       ]);
     $form_builder->submitForm($this, $form_state);
     $this->assertEqual(count($form_state->getErrors()), 1);
-    $this->assertEqual($form_state->getErrors()['single'], t('The referenced entity (%type: %id) does not exist.', array('%type' => 'entity_test', '%id' => 42)));
+    $this->assertEqual($form_state->getErrors()['single'], t('This entity (%type: %id) cannot be referenced.', array('%type' => 'entity_test', '%id' => 42)));
 
     // Do the same tests as above but on an element with '#validate_reference'
     // set to FALSE.
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
index 6fae79b..5c9161e 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
@@ -691,8 +691,8 @@ public function testEntityConstraintValidation() {
       ->setSetting('target_type', 'node')
       ->setSetting('handler_settings', ['target_bundles' => ['article' => 'article']]);
     $reference_field = \Drupal::TypedDataManager()->create($definition);
-    $reference = $reference_field->appendItem(array('entity' => $node));
-    $violations = $reference->validate();
+    $reference_field->appendItem(array('entity' => $node));
+    $violations = $reference_field->validate();
     $this->assertEqual($violations->count(), 1);
 
     $node = entity_create('node', array(
@@ -701,8 +701,8 @@ public function testEntityConstraintValidation() {
       'title' => $this->randomString(),
     ));
     $node->save();
-    $reference->setValue($node);
-    $violations = $reference->validate();
+    $reference_field->entity = $node;
+    $violations = $reference_field->validate();
     $this->assertEqual($violations->count(), 0);
   }
 
diff --git a/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php b/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php
index f74410f..3195e1d 100644
--- a/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityReferenceFieldTest.php
@@ -103,7 +103,7 @@ public function testEntityReferenceFieldValidation() {
     $entity->{$this->fieldName}->target_id = 9999;
     $violations = $entity->{$this->fieldName}->validate();
     $this->assertEqual($violations->count(), 1, 'Validation throws a violation.');
-    $this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%type: %id) does not exist.', array('%type' => $this->referencedEntityType, '%id' => 9999)));
+    $this->assertEqual($violations[0]->getMessage(), t('This entity (%type: %id) cannot be referenced.', array('%type' => $this->referencedEntityType, '%id' => 9999)));
 
     // @todo Implement a test case for invalid bundle references after
     //   https://www.drupal.org/node/2064191 is fixed.
diff --git a/core/modules/system/src/Tests/Entity/EntityValidationTest.php b/core/modules/system/src/Tests/Entity/EntityValidationTest.php
index aa85fa7..81951df 100644
--- a/core/modules/system/src/Tests/Entity/EntityValidationTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityValidationTest.php
@@ -165,7 +165,7 @@ protected function checkValidation($entity_type) {
     $test_entity->set('user_id', 9999);
     $violations = $test_entity->validate();
     $this->assertEqual($violations->count(), 1, 'Validation failed.');
-    $this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%type: %id) does not exist.', array('%type' => 'user', '%id' => 9999)));
+    $this->assertEqual($violations[0]->getMessage(), t('This entity (%type: %id) cannot be referenced.', array('%type' => 'user', '%id' => 9999)));
 
     $test_entity = clone $entity;
     $test_entity->field_test_text->format = $this->randomString(33);
diff --git a/core/modules/system/src/Tests/Entity/ValidReferenceConstraintValidatorTest.php b/core/modules/system/src/Tests/Entity/ValidReferenceConstraintValidatorTest.php
index ef38189..d81a124 100644
--- a/core/modules/system/src/Tests/Entity/ValidReferenceConstraintValidatorTest.php
+++ b/core/modules/system/src/Tests/Entity/ValidReferenceConstraintValidatorTest.php
@@ -65,7 +65,7 @@ public function testValidation() {
 
     // Make sure the information provided by a violation is correct.
     $violation = $violations[0];
-    $this->assertEqual($violation->getMessage(), t('The referenced entity (%type: %id) does not exist.', array(
+    $this->assertEqual($violation->getMessage(), t('This entity (%type: %id) cannot be referenced.', array(
       '%type' => 'user',
       '%id' => $entity->id(),
     )), 'The message for invalid value is correct.');
diff --git a/core/modules/taxonomy/src/Tests/TermValidationTest.php b/core/modules/taxonomy/src/Tests/TermValidationTest.php
index b369737..a0db7fc 100644
--- a/core/modules/taxonomy/src/Tests/TermValidationTest.php
+++ b/core/modules/taxonomy/src/Tests/TermValidationTest.php
@@ -63,7 +63,7 @@ public function testValidation() {
     $term->set('parent', 9999);
     $violations = $term->validate();
     $this->assertEqual(count($violations), 1, 'Violation found when term parent is invalid.');
-    $this->assertEqual($violations[0]->getMessage(), format_string('The referenced entity (%type: %id) does not exist.', array('%type' => 'taxonomy_term', '%id' => 9999)));
+    $this->assertEqual($violations[0]->getMessage(), format_string('This entity (%type: %id) cannot be referenced.', array('%type' => 'taxonomy_term', '%id' => 9999)));
 
     $term->set('parent', 0);
     $violations = $term->validate();
diff --git a/core/modules/user/src/Tests/UserValidationTest.php b/core/modules/user/src/Tests/UserValidationTest.php
index f39e11e..f7d2ffa 100644
--- a/core/modules/user/src/Tests/UserValidationTest.php
+++ b/core/modules/user/src/Tests/UserValidationTest.php
@@ -179,7 +179,7 @@ function testValidation() {
     $violations = $user->validate();
     $this->assertEqual(count($violations), 1);
     $this->assertEqual($violations[0]->getPropertyPath(), 'roles.1');
-    $this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%entity_type: %name) does not exist.', array('%entity_type' => 'user_role', '%name' => 'unknown_role')));
+    $this->assertEqual($violations[0]->getMessage(), t('This entity (%entity_type: %name) cannot be referenced.', array('%entity_type' => 'user_role', '%name' => 'unknown_role')));
   }
 
   /**
diff --git a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
index 25e7393..b488cfe 100644
--- a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
+++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
@@ -184,6 +184,14 @@ public function validateReferenceableEntities(array $ids) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function validateReferenceableNewEntities(array $entities) {
+    // @todo adjust
+    return [];
+  }
+
+  /**
    * Element validate; Check View is valid.
    */
   public static function settingsFormValidate($element, FormStateInterface $form_state, $form) {
