diff --git a/core/core.services.yml b/core/core.services.yml
index 3768035..19054c7 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -140,7 +140,7 @@ services:
     arguments: ['@config.storage', '@event_dispatcher', '@config.typed']
   config.installer:
     class: Drupal\Core\Config\ConfigInstaller
-    arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher']
+    arguments: ['@config.factory', '@config.storage', '@config.typed', '@config.manager', '@event_dispatcher', '@logger.channel.default']
   config.storage:
     class: Drupal\Core\Config\CachedStorage
     arguments: ['@config.storage.active', '@cache.config']
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 91cee77..f1b31d2 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -742,6 +742,8 @@ function install_tasks($install_state) {
     ),
     'install_profile_themes' => array(
     ),
+    'install_install_profile' => array(
+    ),
     'install_import_translations' => array(
       'display_name' => t('Set up translations'),
       'display' => $needs_translations,
@@ -1023,10 +1025,6 @@ function install_base_system(&$install_state) {
   // State can be set to the database now that system.module is installed.
   $modules = $install_state['profile_info']['dependencies'];
 
-  // The installation profile is also a module, which needs to be installed
-  // after all the dependencies have been installed.
-  $modules[] = drupal_get_profile();
-
   \Drupal::state()->set('install_profile_modules', array_diff($modules, array('system')));
   $install_state['base_system_verified'] = TRUE;
 }
@@ -1572,10 +1570,7 @@ function install_profile_modules(&$install_state) {
   // the modules.
   $required = array();
   $non_required = array();
-  // Although the profile module is marked as required, it needs to go after
-  // every dependency, including non-required ones. So clear its required
-  // flag for now to allow it to install late.
-  $files[$install_state['parameters']['profile']]->info['required'] = FALSE;
+
   // Add modules that other modules depend on.
   foreach ($modules as $module) {
     if ($files[$module]->requires) {
@@ -1635,6 +1630,16 @@ function install_profile_themes(&$install_state) {
 }
 
 /**
+ * Installs the install profile.
+ *
+ * @param $install_state
+ *   An array of information about the current installation state.
+ */
+function install_install_profile(&$install_state) {
+  \Drupal::service('module_installer')->install(array(drupal_get_profile()), FALSE);
+}
+
+/**
  * Prepares the system for import and downloads additional translations.
  *
  * @param $install_state
diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 1c7993b..7bd813d 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\Entity\ConfigDependencyManager;
 use Drupal\Core\Site\Settings;
+use Psr\Log\LoggerInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 class ConfigInstaller implements ConfigInstallerInterface {
@@ -57,6 +58,13 @@ class ConfigInstaller implements ConfigInstallerInterface {
   protected $sourceStorage;
 
   /**
+   * The logger.
+   *
+   * @var \Psr\Log\LoggerInterface
+   */
+  protected $logger;
+
+  /**
    * Is configuration being created as part of a configuration sync.
    *
    * @var bool
@@ -76,13 +84,16 @@ class ConfigInstaller implements ConfigInstallerInterface {
    *   The configuration manager.
    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
    *   The event dispatcher.
+   * @param \Psr\Log\LoggerInterface $logger
+   *   The logger.
    */
-  public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher) {
+  public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher, LoggerInterface $logger) {
     $this->configFactory = $config_factory;
     $this->activeStorages[$active_storage->getCollectionName()] = $active_storage;
     $this->typedConfig = $typed_config;
     $this->configManager = $config_manager;
     $this->eventDispatcher = $event_dispatcher;
+    $this->logger = $logger;
   }
 
   /**
@@ -99,26 +110,11 @@ public function installDefaultConfig($type, $name) {
     // Gather information about all the supported collections.
     $collection_info = $this->configManager->getConfigCollectionInfo();
 
-    // Read enabled extensions directly from configuration to avoid circular
-    // dependencies with ModuleHandler and ThemeHandler.
-    $extension_config = $this->configFactory->get('core.extension');
-    $modules = (array) $extension_config->get('module');
-    // Unless we are installing the profile, remove it from the list.
-    if ($install_profile = Settings::get('install_profile')) {
-      if ($name !== $install_profile) {
-        unset($modules[$install_profile]);
-      }
-    }
-    $enabled_extensions = array_keys($modules);
-    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
-
-    // Core can provide configuration.
-    $enabled_extensions[] = 'core';
-
+    $enabled_extensions = $this->getEnabledExtensions();
     foreach ($collection_info->getCollectionNames(TRUE) as $collection) {
       $config_to_install = $this->listDefaultConfigToInstall($type, $name, $collection, $enabled_extensions);
       if (!empty($config_to_install)) {
-        $this->createConfiguration($collection, $config_to_install);
+        $this->createConfiguration($collection, $config_to_install, $enabled_extensions);
       }
     }
 
@@ -146,30 +142,47 @@ public function installDefaultConfig($type, $name) {
    *   The list of configuration objects to create.
    */
   protected function listDefaultConfigToInstall($type, $name, $collection, array $enabled_extensions) {
-    // Get all default configuration owned by this extension.
+    // Get all default configuration owned by this extension that is provided
+    // by other enabled modules and merge it with all the default configuration
+    // that is provided by the extension that is installable.
     $source_storage = $this->getSourceStorage($collection);
-    $config_to_install = $source_storage->listAll($name . '.');
+    return array_merge(
+      $source_storage->listAll($name . '.'),
+      $this->listExtensionProvidedConfig($type, $name, $collection, $enabled_extensions)
+    );
+  }
 
+  /**
+   * Lists the configuration in the extension's config directory.
+   *
+   * @param string $type
+   *   The extension type; e.g., 'module' or 'theme'.
+   * @param string $name
+   *   The name of the module or theme to install default configuration for.
+   * @param string $collection
+   *  The configuration collection to install.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
+   *
+   * @return array
+   *   The list of configuration in the extension's config directory that can be
+   *   installed.
+   */
+  protected function listExtensionProvidedConfig($type, $name, $collection, array $enabled_extensions) {
+    $extension_provided_config = [];
     // If not installing the core base system default configuration, work out if
     // this extension provides default configuration for any other enabled
     // extensions.
-    $extension_path = drupal_get_path($type, $name);
-    if ($type !== 'core' && is_dir($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY)) {
-      $default_storage = new FileStorage($extension_path . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection);
-      $extension_provided_config = array_filter($default_storage->listAll(), function ($config_name) use ($config_to_install, $enabled_extensions) {
-        // Ensure that we have not already discovered the config to install.
-        if (in_array($config_name, $config_to_install)) {
-          return FALSE;
-        }
+    $extension_path = $this->getDefaultConfigDirectory($type, $name);
+    if ($type !== 'core') {
+      $default_storage = new FileStorage($extension_path, $collection);
+      $extension_provided_config = array_filter($default_storage->listAll(), function ($config_name) use ($enabled_extensions) {
         // Ensure the configuration is provided by an enabled module.
         $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
         return in_array($provider, $enabled_extensions);
       });
-
-      $config_to_install = array_merge($config_to_install, $extension_provided_config);
     }
-
-    return $config_to_install;
+    return $extension_provided_config;
   }
 
   /**
@@ -180,7 +193,7 @@ protected function listDefaultConfigToInstall($type, $name, $collection, array $
    * @param array $config_to_install
    *   A list of configuration object names to create.
    */
-  protected function createConfiguration($collection, array $config_to_install) {
+  protected function createConfiguration($collection, array $config_to_install, array $enabled_extensions) {
     // Order the configuration to install in the order of dependencies.
     $data = $this->getSourceStorage($collection)->readMultiple($config_to_install);
     $config_entity_support = $this->configManager->supportsConfigurationEntities($collection);
@@ -191,8 +204,14 @@ protected function createConfiguration($collection, array $config_to_install) {
         ->sortAll();
     }
 
-    // Remove configuration that already exists in the active storage.
-    $config_to_install = array_diff($config_to_install, $this->getActiveStorages($collection)->listAll());
+    if ($config_entity_support) {
+      // Get a list of all configuration that is active and will be installed
+      // for dependency checking.
+      $all_config = array_merge($config_to_install, $this->getActiveStorages($collection)->listAll());
+    }
+    else {
+      $all_config = [];
+    }
 
     foreach ($config_to_install as $name) {
       // Allow config factory overriders to use a custom configuration object if
@@ -208,7 +227,6 @@ protected function createConfiguration($collection, array $config_to_install) {
         $new_config->setData($data[$name]);
       }
       if ($config_entity_support && $entity_type = $this->configManager->getEntityTypeIdByName($name)) {
-
         // If we are syncing do not create configuration entities. Pluggable
         // configuration entities can have dependencies on modules that are
         // not yet enabled. This approach means that any code that expects
@@ -218,6 +236,14 @@ protected function createConfiguration($collection, array $config_to_install) {
         if ($this->isSyncing) {
           continue;
         }
+        // All the configuration that is provided by the extension will have
+        // been dependency checked already. But configuration provided by other
+        // extensions won't have. If this fails just ignore the configuration
+        // and continue.
+        if (!$this->validateDependencies($name, $data[$name], $enabled_extensions, $all_config)) {
+          $this->logger->info('Unable to create %config_name configuration because it has unmet dependencies.', array('%config_name' => $name));
+          continue;
+        }
         $entity_storage = $this->configManager
           ->getEntityManager()
           ->getStorage($entity_type);
@@ -244,15 +270,13 @@ protected function createConfiguration($collection, array $config_to_install) {
    */
   public function installCollectionDefaultConfig($collection) {
     $config_to_install = $this->getSourceStorage($collection)->listAll();
-    $extension_config = $this->configFactory->get('core.extension');
-    $enabled_extensions = array_keys((array) $extension_config->get('module'));
-    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
+    $enabled_extensions = $this->getEnabledExtensions();
     $config_to_install = array_filter($config_to_install, function ($config_name) use ($enabled_extensions) {
       $provider = Unicode::substr($config_name, 0, strpos($config_name, '.'));
       return in_array($provider, $enabled_extensions);
     });
     if (!empty($config_to_install)) {
-      $this->createConfiguration($collection, $config_to_install);
+      $this->createConfiguration($collection, $config_to_install, $enabled_extensions);
       // Reset all the static caches and list caches.
       $this->configFactory->reset();
     }
@@ -330,20 +354,30 @@ public function isSyncing() {
   }
 
   /**
-   * {@inheritdoc}
+   * Finds pre-existing configuration objects for the provided extension.
+   *
+   * Extensions can not be installed if configuration objects exist in the
+   * active storage with the same names. This can happen in a number of ways,
+   * commonly:
+   * - if a user has created configuration with the same name as that provided
+   *   by the extension.
+   * - if the extension provides default configuration that does not depend on
+   *   it and the extension has been uninstalled and is about to the
+   *   reinstalled.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   *
+   * @return array
+   *   Array of configuration objects that already exist keyed by collection.
    */
-  public function findPreExistingConfiguration($type, $name) {
+  protected function findPreExistingConfiguration($type, $name, array $enabled_extensions) {
     $existing_configuration = array();
     // Gather information about all the supported collections.
     $collection_info = $this->configManager->getConfigCollectionInfo();
 
-    // Read enabled extensions directly from configuration to avoid circular
-    // dependencies on ModuleHandler and ThemeHandler.
-    $extension_config = $this->configFactory->get('core.extension');
-    $enabled_extensions = array_keys((array) $extension_config->get('module'));
-    $enabled_extensions += array_keys((array) $extension_config->get('theme'));
-    // Add the extension that will be enabled to the list of enabled extensions.
-    $enabled_extensions[] = $name;
     foreach ($collection_info->getCollectionNames(TRUE) as $collection) {
       $config_to_install = $this->listDefaultConfigToInstall($type, $name, $collection, $enabled_extensions);
       $active_storage = $this->getActiveStorages($collection);
@@ -355,4 +389,173 @@ public function findPreExistingConfiguration($type, $name) {
     }
     return $existing_configuration;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function checkConfigurationToInstall($type, $name) {
+    if ($this->isSyncing()) {
+      // Configuration is assumed to already be checked by the config importer
+      // validation events
+      return;
+    }
+    $enabled_extensions = $this->getEnabledExtensions();
+    // Add the extension that will be enabled to the list of enabled extensions.
+    $enabled_extensions[] = $name;
+
+    // Check the dependencies of configuration provided by the module.
+    $invalid_default_config = $this->findDefaultConfigWithUnmetDependencies($type, $name, $enabled_extensions);
+    if (!empty($invalid_default_config)) {
+      throw UnmetDependenciesException::create($name, $invalid_default_config);
+    }
+
+    // Install profiles can not have config clashes. Configuration that
+    // has the same name as a module's configuration will be used instead.
+    if ($name != $this->drupalGetProfile()) {
+      // Throw an exception if the module being installed contains configuration
+      // that already exits. Additionally, can not continue installing more
+      // modules because those may depend on the current module being installed.
+      $existing_configuration = $this->findPreExistingConfiguration($type, $name, $enabled_extensions);
+      if (!empty($existing_configuration)) {
+        throw PreExistingConfigException::create($name, $existing_configuration);
+      }
+    }
+  }
+
+  /**
+   * Finds default configuration with unmet dependencies.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
+   *
+   * @return array
+   *   List of configuration that has unmet dependencies
+   */
+  protected function findDefaultConfigWithUnmetDependencies($type, $name, array $enabled_extensions) {
+    $default_storage = new FileStorage($this->getDefaultConfigDirectory($type, $name));
+    $list = $this->listExtensionProvidedConfig($type, $name, StorageInterface::DEFAULT_COLLECTION, $enabled_extensions);
+    $all_config = array_merge($this->configFactory->listAll(), $list);
+    return array_filter($list, function($config_name) use ($default_storage, $enabled_extensions, $all_config) {
+      return !$this->validateDependencies($config_name, $default_storage->read($config_name), $enabled_extensions, $all_config);
+    });
+  }
+
+  /**
+   * Validates an array of config data that contains dependency information.
+   *
+   * @param string $config_name
+   *   The name of the configuration object that is being validated.
+   * @param array $data
+   *   Configuration data.
+   * @param array $enabled_extensions
+   *   A list of all the currently enabled modules and themes.
+   * @param array $all_config
+   *   A list of all the active configuration names.
+   *
+   * @return bool
+   *   TRUE if the dependencies are met, FALSE if not.
+   */
+  protected function validateDependencies($config_name, array $data, array $enabled_extensions, array $all_config) {
+    // All the migrate tests will fail if we check since they install the
+    // migrate_drupal module but only set up the dependencies for the single
+    // migration they are testing.
+    if (strpos($config_name, 'migrate.migration.') === 0) {
+      return TRUE;
+    }
+    if (isset($data['dependencies'])) {
+      $all_dependencies = $data['dependencies'];
+
+      // Ensure enforced dependencies are included.
+      if (isset($all_dependencies['enforced'])) {
+        $all_dependencies = array_merge($all_dependencies, $data['dependencies']['enforced']);
+      }
+
+      foreach ($all_dependencies as $type => $dependencies) {
+        $list_to_check = [];
+        switch ($type) {
+          case 'module':
+          case 'theme':
+            $list_to_check = $enabled_extensions;
+            break;
+          case 'config':
+            $list_to_check = $all_config;
+            break;
+        }
+        if (!empty($list_to_check)) {
+          $missing = array_diff($dependencies, $list_to_check);
+          if (!empty($missing)) {
+            return FALSE;
+          }
+        }
+      }
+    }
+    return TRUE;
+  }
+
+  /**
+   * Gets the list of enabled extensions including both modules and themes.
+   *
+   * @return array
+   *   A list of enabled extensions which includes both modules and themes.
+   */
+  protected function getEnabledExtensions() {
+    // Read enabled extensions directly from configuration to avoid circular
+    // dependencies on ModuleHandler and ThemeHandler.
+    $extension_config = $this->configFactory->get('core.extension');
+    $enabled_extensions = (array) $extension_config->get('module');
+    $enabled_extensions += (array) $extension_config->get('theme');
+    // Core can provide configuration.
+    $enabled_extensions['core'] = 'core';
+    return array_keys($enabled_extensions);
+  }
+
+  /**
+   * Gets an extension's default configuration directory.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   *
+   * @return string
+   *   The extension's default configuration directory.
+   */
+  protected function getDefaultConfigDirectory($type, $name) {
+    return $this->drupalGetPath($type, $name) . '/' . InstallStorage::CONFIG_INSTALL_DIRECTORY;
+  }
+
+  /**
+   * Wrapper for drupal_get_path().
+   *
+   * @param $type
+   *   The type of the item; one of 'core', 'profile', 'module', 'theme', or
+   *   'theme_engine'.
+   * @param $name
+   *   The name of the item for which the path is requested. Ignored for
+   *   $type 'core'.
+   *
+   * @return string
+   *   The path to the requested item or an empty string if the item is not
+   *   found.
+   */
+  protected function drupalGetPath($type, $name) {
+    return drupal_get_path($type, $name);
+  }
+
+  /**
+   * Wrapper for drupal_get_profile().
+   *
+   * @return string|null $profile
+   *   The name of the installation profile or NULL if no installation profile is
+   *   currently active. This is the case for example during the first steps of
+   *   the installer or during unit tests.
+   */
+  protected function drupalGetProfile() {
+    return drupal_get_profile();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
index 1d1e7e0..5a94428 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -85,25 +85,16 @@ public function setSyncing($status);
   public function isSyncing();
 
   /**
-   * Finds pre-existing configuration objects for the provided extension.
-   *
-   * Extensions can not be installed if configuration objects exist in the
-   * active storage with the same names. This can happen in a number of ways,
-   * commonly:
-   * - if a user has created configuration with the same name as that provided
-   *   by the extension.
-   * - if the extension provides default configuration that does not depend on
-   *   it and the extension has been uninstalled and is about to the
-   *   reinstalled.
+   * Checks the configuration that will be installed for an extension.
    *
    * @param string $type
    *   Type of extension to install.
    * @param string $name
    *   Name of extension to install.
    *
-   * @return array
-   *   Array of configuration objects that already exist keyed by collection.
+   * @throws \Drupal\Core\Config\UnmetDependenciesException
+   * @throws \Drupal\Core\Config\PreExistingConfigException
    */
-  public function findPreExistingConfiguration($type, $name);
+  public function checkConfigurationToInstall($type, $name);
 
 }
diff --git a/core/lib/Drupal/Core/Config/UnmetDependenciesException.php b/core/lib/Drupal/Core/Config/UnmetDependenciesException.php
new file mode 100644
index 0000000..db7ad9c
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/UnmetDependenciesException.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\UnmetDependenciesException.
+ */
+
+namespace Drupal\Core\Config;
+
+use Drupal\Component\Utility\String;
+use Drupal\Core\StringTranslation\TranslationInterface;
+
+/**
+ * An exception thrown if configuration has unmet dependencies.
+ */
+class UnmetDependenciesException extends ConfigException {
+
+  /**
+   * A list of configuration objects that have unmet dependencies.
+   *
+   * @var array
+   */
+  protected $configObjects = [];
+
+  /**
+   * The name of the extension that is being installed.
+   *
+   * @var string
+   */
+  protected $extension;
+
+  /**
+   * Gets the list of configuration objects that have unmet dependencies.
+   *
+   * @return array
+   *   A list of configuration objects that have unmet dependencies.
+   */
+  public function getConfigObjects() {
+    return $this->configObjects;
+  }
+
+  /**
+   * Gets the name of the extension that is being installed.
+   *
+   * @return string
+   *   The name of the extension that is being installed.
+   */
+  public function getExtension() {
+    return $this->extension;
+  }
+
+  /**
+   * Gets a translated message from the exception.
+   *
+   * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation
+   *   The string translation service.
+   *
+   * @return string
+   */
+  public function getTranslatedMessage(TranslationInterface $string_translation, $extension) {
+    return $string_translation->formatPlural(
+      count($this->getConfigObjects()),
+      'Unable to install @extension, %config_names has unmet dependencies.',
+      'Unable to install @extension, %config_names have unmet dependencies.',
+      [
+        '%config_names' => implode(', ', $this->getConfigObjects()),
+        '@extension' => $extension,
+      ]
+    );
+  }
+
+  /**
+   * Creates an exception for an extension and a list of configuration objects.
+   *
+   * @param $extension
+   *   The name of the extension that is being installed.
+   * @param array $config_objects
+   *   A list of configuration objects that already exist in active
+   *   configuration, keyed by config collection.
+   *
+   * @return \Drupal\Core\Config\PreExistingConfigException
+   */
+  public static function create($extension, array $config_objects) {
+    $message = String::format('Configuration objects (@config_names) provided by @extension have unmet dependencies',
+      array(
+        '@config_names' => implode(', ', $config_objects),
+        '@extension' => $extension
+      )
+    );
+    $e = new static($message);
+    $e->configObjects = $config_objects;
+    $e->extension = $extension;
+    return $e;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index dba7a94..af2ab64 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -151,17 +151,9 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
           )));
         }
 
-        // Install profiles can not have config clashes. Configuration that
-        // has the same name as a module's configuration will be used instead.
-        if ($module != drupal_get_profile()) {
-          // Validate default configuration of this module. Bail if unable to
-          // install. Should not continue installing more modules because those
-          // may depend on this one.
-          $existing_configuration = $config_installer->findPreExistingConfiguration('module', $module);
-          if (!empty($existing_configuration)) {
-            throw PreExistingConfigException::create($module, $existing_configuration);
-          }
-        }
+        // Check the validity of the default configuration. This will throw
+        // exceptions if the configuration is not valid.
+        $config_installer->checkConfigurationToInstall('module', $module);
 
         $extension_config
           ->set("module.$module", 0)
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 9529c8a..79ca84c 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -258,10 +258,7 @@ public function install(array $theme_list, $install_dependencies = TRUE) {
 
       // Validate default configuration of the theme. If there is existing
       // configuration then stop installing.
-      $existing_configuration = $this->configInstaller->findPreExistingConfiguration('theme', $key);
-      if (!empty($existing_configuration)) {
-        throw PreExistingConfigException::create($key, $existing_configuration);
-      }
+      $this->configInstaller->checkConfigurationToInstall('theme', $key);
 
       // The value is not used; the weight is ignored for themes currently.
       $extension_config
diff --git a/core/modules/block/src/Tests/BlockStorageUnitTest.php b/core/modules/block/src/Tests/BlockStorageUnitTest.php
index ff4ba29..eb3f8eb 100644
--- a/core/modules/block/src/Tests/BlockStorageUnitTest.php
+++ b/core/modules/block/src/Tests/BlockStorageUnitTest.php
@@ -149,6 +149,7 @@ protected function deleteTests() {
    * Tests the installation of default blocks.
    */
   public function testDefaultBlocks() {
+    \Drupal::service('theme_handler')->install(['classy']);
     $entities = $this->controller->loadMultiple();
     $this->assertTrue(empty($entities), 'There are no blocks initially.');
 
diff --git a/core/modules/block_content/src/Tests/BlockContentPageViewTest.php b/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
index 90adab7..0564c60 100644
--- a/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentPageViewTest.php
@@ -19,7 +19,7 @@ class BlockContentPageViewTest extends BlockContentTestBase {
    *
    * @var array
    */
-  public static $modules = array('block', 'block_content', 'block_content_test');
+  public static $modules = array('block_content_test');
 
   /**
    * Checks block edit and fallback functionality.
diff --git a/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml b/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
index 747efa4..16e4bc7 100644
--- a/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
+++ b/core/modules/block_content/tests/modules/block_content_test/block_content_test.info.yml
@@ -4,3 +4,5 @@ description: "Support module for custom block related testing."
 package: Testing
 version: VERSION
 core: 8.x
+dependencies:
+  - block_content
diff --git a/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml b/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
index ed83291..4cc2360 100644
--- a/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
+++ b/core/modules/block_content/tests/modules/block_content_test/config/install/block.block.foobargorilla.yml
@@ -4,7 +4,7 @@ dependencies:
   module:
     - block_content
   theme:
-    - stark
+    - classy
 id: foobargorilla
 theme: classy
 region: content
diff --git a/core/modules/book/config/install/core.entity_view_mode.node.print.yml b/core/modules/book/config/install/core.entity_view_mode.node.print.yml
index 512d581..de47b0c 100644
--- a/core/modules/book/config/install/core.entity_view_mode.node.print.yml
+++ b/core/modules/book/config/install/core.entity_view_mode.node.print.yml
@@ -5,4 +5,8 @@ cache: true
 targetEntityType: node
 dependencies:
   module:
+    - book
     - node
+  enforced:
+    module:
+      - book
diff --git a/core/modules/config/src/Tests/ConfigInstallTest.php b/core/modules/config/src/Tests/ConfigInstallTest.php
index 2da9e53..4cbc984 100644
--- a/core/modules/config/src/Tests/ConfigInstallTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallTest.php
@@ -48,11 +48,8 @@ function testModuleInstallation() {
     $this->assertFalse(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install does not exist.');
 
     // Install the test module.
-    $this->enableModules(array('config_test', 'config_schema_test'));
-    $this->installConfig(array('config_test', 'config_schema_test'));
-
-    // After module installation the new schema should exist.
-    $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.');
+    $this->enableModules(array('config_test'));
+    $this->installConfig(array('config_test'));
 
     // Verify that default module config exists.
     \Drupal::configFactory()->reset($default_config);
@@ -71,6 +68,13 @@ function testModuleInstallation() {
     $this->assertFalse(isset($GLOBALS['hook_config_test']['predelete']));
     $this->assertFalse(isset($GLOBALS['hook_config_test']['delete']));
 
+    // Install the schema test module.
+    $this->enableModules(array('config_schema_test'));
+    $this->installConfig(array('config_schema_test'));
+
+    // After module installation the new schema should exist.
+    $this->assertTrue(\Drupal::service('config.typed')->hasConfigSchema('config_schema_test.schema_in_install'), 'Configuration schema for config_schema_test.schema_in_install exists.');
+
     // Ensure that data type casting is applied during config installation.
     $config = $this->config('config_schema_test.schema_in_install');
     $this->assertIdentical($config->get('integer'), 1);
diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php
index b04ce39..5748d51 100644
--- a/core/modules/config/src/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php
@@ -214,4 +214,21 @@ public function testPreExistingConfigInstall() {
       $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default) provided by config_clash_test_theme already exist in active configuration');
     }
   }
+
+  /**
+   * Tests unmet dependencies detection.
+   */
+  public function testUnmetDependenciesInstall() {
+    $this->drupalLogin($this->adminUser);
+    // We need to install separately since config_install_dependency_test does
+    // not depend on config_test and order is important.
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
+    $this->assertRaw('Unable to install Config install dependency test, <em class="placeholder">config_test.dynamic.other_module_test_with_dependency</em> has unmet dependencies.');
+
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_other_module_config_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
+    $this->rebuildContainer();
+    $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
+  }
 }
diff --git a/core/modules/config/src/Tests/ConfigOtherModuleTest.php b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
index 082e485..886f59e 100644
--- a/core/modules/config/src/Tests/ConfigOtherModuleTest.php
+++ b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\StorageInterface;
+use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -97,6 +98,29 @@ public function testUninstall() {
   }
 
   /**
+   * Tests the configuration with unmet dependencies is not installed.
+   */
+  public function testDependencyChecking() {
+    $this->installModule('config_install_dependency_test');
+    $this->installModule('config_test');
+    $this->assertFalse(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration is ignored during install.');
+    $this->uninstallModule('config_install_dependency_test');
+
+    try {
+      $this->installModule('config_install_dependency_test');
+      $this->fail('Expected UnmetDependenciesException not thrown.');
+    }
+    catch (UnmetDependenciesException $e) {
+      $this->assertEqual($e->getExtension(), 'config_install_dependency_test');
+      $this->assertEqual($e->getConfigObjects(), ['config_test.dynamic.other_module_test_with_dependency']);
+      $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.other_module_test_with_dependency) provided by config_install_dependency_test have unmet dependencies');
+    }
+    $this->installModule('config_other_module_config_test');
+    $this->installModule('config_install_dependency_test');
+    $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
+  }
+
+  /**
    * Installs a module.
    *
    * @param string $module
diff --git a/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml b/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml
new file mode 100644
index 0000000..69470f8
--- /dev/null
+++ b/core/modules/config/tests/config_install_dependency_test/config/install/config_test.dynamic.other_module_test_with_dependency.yml
@@ -0,0 +1,11 @@
+id: other_module_test_with_dependency
+label: 'Other module test with dependency'
+weight: 0
+style: ''
+status: true
+langcode: en
+protected_property: Default
+dependencies:
+  enforced:
+    module:
+      - config_other_module_config_test
diff --git a/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml b/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml
new file mode 100644
index 0000000..e9b3c72
--- /dev/null
+++ b/core/modules/config/tests/config_install_dependency_test/config_install_dependency_test.info.yml
@@ -0,0 +1,5 @@
+name: 'Config install dependency test'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/node/config/install/views.view.content_recent.yml b/core/modules/node/config/install/views.view.content_recent.yml
index bc12a13..4cb1dd7 100644
--- a/core/modules/node/config/install/views.view.content_recent.yml
+++ b/core/modules/node/config/install/views.view.content_recent.yml
@@ -423,3 +423,5 @@ display:
     id: block_1
     display_title: Block
     position: 1
+    display_options:
+      display_extenders: {  }
diff --git a/core/modules/system/src/Controller/ThemeController.php b/core/modules/system/src/Controller/ThemeController.php
index 7126a7e..d82f908 100644
--- a/core/modules/system/src/Controller/ThemeController.php
+++ b/core/modules/system/src/Controller/ThemeController.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Routing\RouteBuilderIndicatorInterface;
@@ -144,6 +145,9 @@ public function install(Request $request) {
           'error'
         );
       }
+      catch (UnmetDependenciesException $e) {
+        drupal_set_message($e->getTranslatedMessage($this->getStringTranslation(), $theme), 'error');
+      }
 
       return $this->redirect('system.themes_page');
     }
diff --git a/core/modules/system/src/Form/ModulesListConfirmForm.php b/core/modules/system/src/Form/ModulesListConfirmForm.php
index b3c7977..5449b41 100644
--- a/core/modules/system/src/Form/ModulesListConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesListConfirmForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Form;
 
 use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -176,6 +177,13 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         );
         return;
       }
+      catch (UnmetDependenciesException $e) {
+        drupal_set_message(
+          $e->getTranslatedMessage($this->getStringTranslation(), $this->modules['install'][$e->getExtension()]),
+          'error'
+        );
+        return;
+      }
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 2e80482..90a6e9f 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\UnmetDependenciesException;
 use Drupal\Core\Controller\TitleResolverInterface;
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -536,6 +537,13 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         );
         return;
       }
+      catch (UnmetDependenciesException $e) {
+        drupal_set_message(
+          $e->getTranslatedMessage($this->getStringTranslation(), $modules['install'][$e->getExtension()]),
+          'error'
+        );
+        return;
+      }
     }
 
     // Gets module list after install process, flushes caches and displays a
diff --git a/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
index 37a0bf8..05d5e27 100644
--- a/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
+++ b/core/modules/system/tests/themes/test_basetheme/config/install/core.date_format.fancy.yml
@@ -7,3 +7,7 @@ status: true
 langcode: en
 locked: false
 pattern: 'U'
+dependencies:
+  enforced:
+    theme:
+      - test_basetheme
diff --git a/core/profiles/minimal/minimal.info.yml b/core/profiles/minimal/minimal.info.yml
index 628dcd3..d1f83de 100644
--- a/core/profiles/minimal/minimal.info.yml
+++ b/core/profiles/minimal/minimal.info.yml
@@ -7,3 +7,5 @@ dependencies:
   - node
   - block
   - dblog
+themes:
+  - stark
