diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index 72ae554..c02a132 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -22,11 +22,11 @@ class ConfigInstaller implements ConfigInstallerInterface {
   protected $configFactory;
 
   /**
-   * The active configuration storage.
+   * The active configuration storages, keyed by collection.
    *
-   * @var \Drupal\Core\Config\StorageInterface
+   * @var \Drupal\Core\Config\StorageInterface[]
    */
-  protected $activeStorage;
+  protected $activeStorages;
 
   /**
    * The typed configuration manager.
@@ -79,7 +79,7 @@ class ConfigInstaller implements ConfigInstallerInterface {
    */
   public function __construct(ConfigFactoryInterface $config_factory, StorageInterface $active_storage, TypedConfigManagerInterface $typed_config, ConfigManagerInterface $config_manager, EventDispatcherInterface $event_dispatcher) {
     $this->configFactory = $config_factory;
-    $this->activeStorage = $active_storage;
+    $this->activeStorages[$active_storage->getCollectionName()] = $active_storage;
     $this->typedConfig = $typed_config;
     $this->configManager = $config_manager;
     $this->eventDispatcher = $event_dispatcher;
@@ -119,7 +119,7 @@ public function installDefaultConfig($type, $name) {
     $enabled_extensions[] = 'core';
 
     foreach ($collection_info->getCollectionNames(TRUE) as $collection) {
-      $config_to_install = $this->listDefaultConfigCollection($collection, $type, $name, $enabled_extensions);
+      $config_to_install = $this->listDefaultConfigToInstall($type, $name, $collection, $enabled_extensions);
       if (!empty($config_to_install)) {
         $this->createConfiguration($collection, $config_to_install);
       }
@@ -130,21 +130,25 @@ public function installDefaultConfig($type, $name) {
   }
 
   /**
-   * Installs default configuration for a particular collection.
+   * Lists default configuration for an extension that is available to install.
+   *
+   * This looks in the extension's config/install directory and all of the
+   * currently enabled extensions config/install directories for configuration
+   * that begins with the extension's name.
    *
-   * @param string $collection
-   *  The configuration collection to install.
    * @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 objects to create.
    */
-  protected function listDefaultConfigCollection($collection, $type, $name, array $enabled_extensions) {
+  protected function listDefaultConfigToInstall($type, $name, $collection, array $enabled_extensions) {
     // Get all default configuration owned by this extension.
     $source_storage = $this->getSourceStorage($collection);
     $config_to_install = $source_storage->listAll($name . '.');
@@ -155,16 +159,17 @@ protected function listDefaultConfigCollection($collection, $type, $name, array
     $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);
-      $other_module_config = array_filter($default_storage->listAll(), function ($value) use ($name) {
-        return !preg_match('/^' . $name . '\./', $value);
-      });
-
-      $other_module_config = array_filter($other_module_config, function ($config_name) use ($enabled_extensions) {
+      $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;
+        }
+        // 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, $other_module_config);
+      $config_to_install = array_merge($config_to_install, $extension_provided_config);
     }
 
     return $config_to_install;
@@ -190,7 +195,7 @@ protected function createConfiguration($collection, array $config_to_install) {
     }
 
     // Remove configuration that already exists in the active storage.
-    $config_to_install = array_diff($config_to_install, $this->getActiveStorage($collection)->listAll());
+    $config_to_install = array_diff($config_to_install, $this->getActiveStorages($collection)->listAll());
 
     foreach ($config_to_install as $name) {
       // Allow config factory overriders to use a custom configuration object if
@@ -200,7 +205,7 @@ protected function createConfiguration($collection, array $config_to_install) {
         $new_config = $overrider->createConfigObject($name, $collection);
       }
       else {
-        $new_config = new Config($name, $this->getActiveStorage($collection), $this->eventDispatcher, $this->typedConfig);
+        $new_config = new Config($name, $this->getActiveStorages($collection), $this->eventDispatcher, $this->typedConfig);
       }
       if ($data[$name] !== FALSE) {
         $new_config->setData($data[$name]);
@@ -221,7 +226,7 @@ protected function createConfiguration($collection, array $config_to_install) {
           ->getStorage($entity_type);
         // It is possible that secondary writes can occur during configuration
         // creation. Updates of such configuration are allowed.
-        if ($this->getActiveStorage($collection)->exists($name)) {
+        if ($this->getActiveStorages($collection)->exists($name)) {
           $id = $entity_storage->getIDFromConfigName($name, $entity_storage->getEntityType()->getConfigPrefix());
           $entity = $entity_storage->load($id);
           $entity = $entity_storage->updateFromStorageRecord($entity, $new_config->get());
@@ -290,7 +295,7 @@ public function getSourceStorage($collection = StorageInterface::DEFAULT_COLLECT
       // Default to using the ExtensionInstallStorage which searches extension's
       // config directories for default configuration. Only include the profile
       // configuration during Drupal installation.
-      $this->sourceStorage = new ExtensionInstallStorage($this->activeStorage, InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection, drupal_installation_attempted());
+      $this->sourceStorage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection, drupal_installation_attempted());
     }
     if ($this->sourceStorage->getCollectionName() != $collection) {
       $this->sourceStorage = $this->sourceStorage->createCollection($collection);
@@ -308,11 +313,11 @@ public function getSourceStorage($collection = StorageInterface::DEFAULT_COLLECT
    * @return \Drupal\Core\Config\StorageInterface
    *   The configuration storage that provides the default configuration.
    */
-  protected function getActiveStorage($collection = StorageInterface::DEFAULT_COLLECTION) {
-    if ($this->activeStorage->getCollectionName() != $collection) {
-      $this->activeStorage = $this->activeStorage->createCollection($collection);
+  protected function getActiveStorages($collection = StorageInterface::DEFAULT_COLLECTION) {
+    if (!isset($this->activeStorages[$collection])) {
+      $this->activeStorages[$collection] = reset($this->activeStorages)->createCollection($collection);
     }
-    return $this->activeStorage;
+    return $this->activeStorages[$collection];
   }
 
   /**
@@ -329,4 +334,31 @@ public function setSyncing($status) {
   public function isSyncing() {
     return $this->isSyncing;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findPreExistingConfiguration($type, $name) {
+    $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);
+      foreach ($config_to_install as $config_name) {
+        if ($active_storage->exists($config_name)) {
+          $existing_configuration[$collection][] = $config_name;
+        }
+      }
+    }
+    return $existing_configuration;
+  }
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
index 13e5b0e..1d1e7e0 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstallerInterface.php
@@ -84,4 +84,26 @@ 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.
+   *
+   * @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);
+
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index da0fa98..e3fcaf8 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -110,6 +110,19 @@ public function getEntityTypeIdByName($name) {
   /**
    * {@inheritdoc}
    */
+  public function loadConfigEntityByName($name) {
+    $entity_type_id = $this->getEntityTypeIdByName($name);
+    if ($entity_type_id) {
+      $entity_type = $this->entityManager->getDefinition($entity_type_id);
+      $id = substr($name, strlen($entity_type->getConfigPrefix()) + 1);
+      return $this->entityManager->getStorage($entity_type_id)->load($id);
+    }
+    return NULL;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getEntityManager() {
     return $this->entityManager;
   }
diff --git a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
index c5fdec1..79f4a7e 100644
--- a/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
+++ b/core/lib/Drupal/Core/Config/ConfigManagerInterface.php
@@ -24,6 +24,17 @@
   public function getEntityTypeIdByName($name);
 
   /**
+   * Loads a configuration entity using the configuration name.
+   *
+   * @param string $name
+   *   The configuration object name.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface|null
+   *   The configuration entity or NULL if it does not exist.
+   */
+  public function loadConfigEntityByName($name);
+
+  /**
    * Gets the entity manager.
    *
    * @return \Drupal\Core\Entity\EntityManagerInterface
diff --git a/core/lib/Drupal/Core/Config/PreExistingConfigException.php b/core/lib/Drupal/Core/Config/PreExistingConfigException.php
new file mode 100644
index 0000000..8fe8a6a
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/PreExistingConfigException.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\PreExistingConfigException.
+ */
+
+namespace Drupal\Core\Config;
+
+use Drupal\Component\Utility\String;
+
+/**
+ * An exception thrown if configuration with the same name already exists.
+ */
+class PreExistingConfigException extends ConfigException {
+
+  /**
+   * A list of configuration objects that already exist in active configuration.
+   *
+   * @var array
+   */
+  protected $configObjects = [];
+
+  /**
+   * The name of the module that is being installed.
+   *
+   * @var string
+   */
+  protected $extension;
+
+  /**
+   * Gets the list of configuration objects that already exist.
+   *
+   * @return array
+   *   A list of configuration objects that already exist in active
+   *   configuration keyed by collection.
+   */
+  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;
+  }
+
+  /**
+   * 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 already exist in active configuration',
+      array(
+        '@config_names' => implode(', ', static::flattenConfigObjects($config_objects)),
+        '@extension' => $extension
+      )
+    );
+    $e = new static($message);
+    $e->configObjects = $config_objects;
+    $e->extension = $extension;
+    return $e;
+  }
+
+  /**
+   * Flattens the config object array to a single dimensional list.
+   *
+   * @param array $config_objects
+   *   A list of configuration objects that already exist in active
+   *   configuration, keyed by config collection.
+   *
+   * @return array
+   *   A list of configuration objects that have been prefixed with their
+   *   collection.
+   */
+  public static function flattenConfigObjects(array $config_objects) {
+    $flat_config_objects = array();
+    foreach ($config_objects as $collection => $config_names) {
+      $config_names = array_map(function ($config_name) use ($collection) {
+        if ($collection != StorageInterface::DEFAULT_COLLECTION) {
+          $config_name = str_replace('.', DIRECTORY_SEPARATOR, $collection) . DIRECTORY_SEPARATOR . $config_name;
+        }
+        return $config_name;
+      }, $config_names);
+      $flat_config_objects = array_merge($flat_config_objects, $config_names);
+    }
+    return $flat_config_objects;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 6cb8363..dba7a94 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -10,6 +10,8 @@
 use Drupal\Component\Serialization\Yaml;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\StorageInterface;
 use Drupal\Core\DrupalKernelInterface;
 use Drupal\Component\Utility\String;
 
@@ -149,6 +151,18 @@ 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);
+          }
+        }
+
         $extension_config
           ->set("module.$module", 0)
           ->set('module', module_config_sort($extension_config->get('module')))
diff --git a/core/lib/Drupal/Core/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php
index 2f0fd94..d21e256 100644
--- a/core/lib/Drupal/Core/Extension/ThemeHandler.php
+++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Config\ConfigInstallerInterface;
 use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Routing\RouteBuilderIndicatorInterface;
 use Drupal\Core\State\StateInterface;
 use Psr\Log\LoggerInterface;
@@ -255,6 +256,13 @@ 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);
+      }
+
       // The value is not used; the weight is ignored for themes currently.
       $extension_config
         ->set("theme.$key", 0)
diff --git a/core/modules/config/src/Tests/ConfigInstallTest.php b/core/modules/config/src/Tests/ConfigInstallTest.php
index 06038e8..2da9e53 100644
--- a/core/modules/config/src/Tests/ConfigInstallTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\StorageInterface;
 use Drupal\simpletest\KernelTestBase;
 
 /**
@@ -115,6 +117,21 @@ public function testCollectionInstallationCollections() {
       $this->assertEqual($collection, $data['collection']);
     }
 
+    // Tests that clashing configuration in collections is detected.
+    try {
+      \Drupal::service('module_installer')->install(['config_collection_clash_install_test']);
+      $this->fail('Expected PreExistingConfigException not thrown.');
+    }
+    catch (PreExistingConfigException $e) {
+      $this->assertEqual($e->getExtension(), 'config_collection_clash_install_test');
+      $this->assertEqual($e->getConfigObjects(), [
+        'another_collection' => ['config_collection_install_test.test'],
+        'collection.test1' => ['config_collection_install_test.test'],
+        'collection.test2' => ['config_collection_install_test.test'],
+      ]);
+      $this->assertEqual($e->getMessage(), 'Configuration objects (another_collection/config_collection_install_test.test, collection/test1/config_collection_install_test.test, collection/test2/config_collection_install_test.test) provided by config_collection_clash_install_test already exist in active configuration');
+    }
+
     // Test that the we can use the config installer to install all the
     // available default configuration in a particular collection for enabled
     // extensions.
diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php
index 1fecc90..b04ce39 100644
--- a/core/modules/config/src/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php
@@ -2,12 +2,15 @@
 
 /**
  * @file
- * Definition of Drupal\config\Tests\ConfigInstallTest.
+ * Contains \Drupal\config\Tests\ConfigInstallWebTest.
  */
 
 namespace Drupal\config\Tests;
 
 use Drupal\Core\Config\InstallStorage;
+use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\StorageInterface;
+use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Core\Config\FileStorage;
 
@@ -20,11 +23,18 @@
 class ConfigInstallWebTest extends WebTestBase {
 
   /**
+   * The admin user used in this test.
+   */
+  protected $adminUser;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
+    $this->adminUser = $this->drupalCreateUser(array('administer modules', 'administer themes'));
+
     // Ensure the global variable being asserted by this test does not exist;
     // a previous test executed in this request/process might have set it.
     unset($GLOBALS['hook_config_test']);
@@ -82,6 +92,18 @@ function testIntegrationModuleReinstallation() {
     $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
 
     // Reinstall the integration module.
+    try {
+      \Drupal::service('module_installer')->install(array('config_integration_test'));
+      $this->fail('Expected PreExistingConfigException not thrown.');
+    }
+    catch (PreExistingConfigException $e) {
+      $this->assertEqual($e->getExtension(), 'config_integration_test');
+      $this->assertEqual($e->getConfigObjects(), [StorageInterface::DEFAULT_COLLECTION => ['config_test.dynamic.config_integration_test']]);
+      $this->assertEqual($e->getMessage(), 'Configuration objects (config_test.dynamic.config_integration_test) provided by config_integration_test already exist in active configuration');
+    }
+
+    // Delete the configuration entity so that the install will work.
+    $config_entity->delete();
     \Drupal::service('module_installer')->install(array('config_integration_test'));
 
     // Verify the integration module's config was re-installed.
@@ -91,10 +113,10 @@ function testIntegrationModuleReinstallation() {
     $this->assertIdentical($config_static->isNew(), FALSE);
     $this->assertIdentical($config_static->get('foo'), 'default setting');
 
-    // Verify the customized integration config still exists.
-    $config_entity = $this->config($default_configuration_entity);
+    // Verify the integration config is using the default.
+    $config_entity = \Drupal::config($default_configuration_entity);
     $this->assertIdentical($config_entity->isNew(), FALSE);
-    $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
+    $this->assertIdentical($config_entity->get('label'), 'Default integration config label');
   }
 
   /**
@@ -132,21 +154,64 @@ function testInstallProfileConfigOverwrite() {
     // created from the testing install profile's system.cron.yml file.
     $config = $this->config($config_name);
     $this->assertIdentical($config->get(), $expected_profile_data);
+  }
 
-    // Turn on the test module, which will attempt to replace the
-    // configuration data. This attempt to replace the active configuration
-    // should be ignored.
-    \Drupal::service('module_installer')->install(array('config_existing_default_config_test'));
-
-    // Verify that the test module has not been able to change the data.
-    $config = $this->config($config_name);
-    $this->assertIdentical($config->get(), $expected_profile_data);
-
-    // Disable and uninstall the test module.
-    \Drupal::service('module_installer')->uninstall(array('config_existing_default_config_test'));
-
-    // Verify that the data hasn't been altered by removing the test module.
-    $config = $this->config($config_name);
-    $this->assertIdentical($config->get(), $expected_profile_data);
+  /**
+   * Tests pre-existing configuration detection.
+   */
+  public function testPreExistingConfigInstall() {
+    $this->drupalLogin($this->adminUser);
+
+    // Try to install config_install_fail_test and config_test. Doing this
+    // will install the config_test module first because it is a dependency of
+    // config_install_fail_test.
+    // @see \Drupal\system\Form\ModulesListForm::submitForm()
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE, 'modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default</em> already exists in active configuration.');
+
+    // Uninstall the config_test module to test the confirm form.
+    $this->drupalPostForm('admin/modules/uninstall', array('uninstall[config_test]' => TRUE), t('Uninstall'));
+    $this->drupalPostForm(NULL, array(), t('Uninstall'));
+
+    // Try to install config_install_fail_test without selecting config_test.
+    // The user is shown a confirm form because the config_test module is a
+    // dependency.
+    // @see \Drupal\system\Form\ModulesListConfirmForm::submitForm()
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm(NULL, array(), t('Continue'));
+    $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default</em> already exists in active configuration.');
+
+    // Test that collection configuration clashes during a module install are
+    // reported correctly.
+    \Drupal::service('module_installer')->install(['language']);
+    $this->rebuildContainer();
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+    \Drupal::languageManager()
+      ->getLanguageConfigOverride('fr', 'config_test.dynamic.dotted.default')
+      ->set('label', 'Je suis Charlie')
+      ->save();
+
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default</em> already exist in active configuration.');
+
+    // Test installing a theme through the UI that has existing configuration.
+    // This relies on the fact the config_test has been installed and created
+    // the config_test.dynamic.dotted.default configuration and the translation
+    // override created still exists.
+    $this->drupalGet('admin/appearance');
+    $url = $this->xpath("//a[contains(@href,'config_clash_test_theme') and contains(@href,'/install?')]/@href")[0];
+    $this->drupalGet($this->getAbsoluteUrl($url));
+    $this->assertRaw('Unable to install config_clash_test_theme, <em class="placeholder">config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default</em> already exist in active configuration.');
+
+    // Test installing a theme through the API that has existing configuration.
+    try {
+      \Drupal::service('theme_handler')->install(['config_clash_test_theme']);
+      $this->fail('Expected PreExistingConfigException not thrown.');
+    }
+    catch (PreExistingConfigException $e) {
+      $this->assertEqual($e->getExtension(), 'config_clash_test_theme');
+      $this->assertEqual($e->getConfigObjects(), [StorageInterface::DEFAULT_COLLECTION => ['config_test.dynamic.dotted.default'], 'language.fr' => ['config_test.dynamic.dotted.default']]);
+      $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');
+    }
   }
 }
diff --git a/core/modules/config/src/Tests/ConfigOtherModuleTest.php b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
index 5737d78..082e485 100644
--- a/core/modules/config/src/Tests/ConfigOtherModuleTest.php
+++ b/core/modules/config/src/Tests/ConfigOtherModuleTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\config\Tests;
 
+use Drupal\Core\Config\PreExistingConfigException;
+use Drupal\Core\Config\StorageInterface;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -57,10 +59,18 @@ public function testInstallOtherModuleFirst() {
     // Default configuration provided by config_test should still exist.
     $this->assertTrue(entity_load('config_test', 'dotted.default', TRUE), 'The configuration is not deleted.');
 
-    // Re-enable module to test that default config is unchanged.
-    $this->installModule('config_other_module_config_test');
-    $config_entity = entity_load('config_test', 'other_module_test', TRUE);
-    $this->assertEqual($config_entity->get('style'), "The piano ain't got no wrong notes.", 'Re-enabling the module does not install default config over the existing config entity.');
+    // Re-enable module to test that pre-existing default configuration throws
+    // an error.
+    $msg = "The expected PreExistingConfigException is thrown by reinstalling config_other_module_config_test.";
+    try {
+      $this->installModule('config_other_module_config_test');
+      $this->fail($msg);
+    }
+    catch (PreExistingConfigException $e) {
+      $this->pass($msg);
+      $this->assertEqual($e->getExtension(), 'config_other_module_config_test');
+      $this->assertEqual($e->getConfigObjects(), [StorageInterface::DEFAULT_COLLECTION => ['config_test.dynamic.other_module_test']]);
+    }
   }
 
   /**
diff --git a/core/modules/config/tests/config_clash_test_theme/config/install/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_clash_test_theme/config/install/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..eb94849
--- /dev/null
+++ b/core/modules/config/tests/config_clash_test_theme/config/install/config_test.dynamic.dotted.default.yml
@@ -0,0 +1,7 @@
+# Clashes with default configuration provided by the config_test module.
+id: dotted.default
+label: 'Config install fail'
+weight: 0
+protected_property: Default
+# Intentionally commented out to verify default status behavior.
+# status: 1
diff --git a/core/modules/config/tests/config_clash_test_theme/config/install/language/fr/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_clash_test_theme/config/install/language/fr/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..e73dec0
--- /dev/null
+++ b/core/modules/config/tests/config_clash_test_theme/config/install/language/fr/config_test.dynamic.dotted.default.yml
@@ -0,0 +1,2 @@
+# Clashes with default configuration provided by the config_test module.
+label: 'Je suis'
diff --git a/core/modules/config/tests/config_clash_test_theme/config_clash_test_theme.info.yml b/core/modules/config/tests/config_clash_test_theme/config_clash_test_theme.info.yml
new file mode 100644
index 0000000..2ff354d
--- /dev/null
+++ b/core/modules/config/tests/config_clash_test_theme/config_clash_test_theme.info.yml
@@ -0,0 +1,10 @@
+name: 'Test theme for configuration clash detection'
+type: theme
+description: 'Test theme for configuration clash detection'
+version: VERSION
+base theme: classy
+core: 8.x
+regions:
+  content: Content
+  left: Left
+  right: Right
diff --git a/core/modules/config/tests/config_collection_clash_install_test/config/install/another_collection/config_collection_install_test.test.yml b/core/modules/config/tests/config_collection_clash_install_test/config/install/another_collection/config_collection_install_test.test.yml
new file mode 100644
index 0000000..0337f93
--- /dev/null
+++ b/core/modules/config/tests/config_collection_clash_install_test/config/install/another_collection/config_collection_install_test.test.yml
@@ -0,0 +1 @@
+collection: another_collection
diff --git a/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test1/config_collection_install_test.test.yml b/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test1/config_collection_install_test.test.yml
new file mode 100644
index 0000000..8bdebee
--- /dev/null
+++ b/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test1/config_collection_install_test.test.yml
@@ -0,0 +1 @@
+collection: collection.test1
diff --git a/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test2/config_collection_install_test.test.yml b/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test2/config_collection_install_test.test.yml
new file mode 100644
index 0000000..b5ae44c
--- /dev/null
+++ b/core/modules/config/tests/config_collection_clash_install_test/config/install/collection/test2/config_collection_install_test.test.yml
@@ -0,0 +1 @@
+collection: collection.test2
diff --git a/core/modules/config/tests/config_collection_clash_install_test/config/install/entity/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_collection_clash_install_test/config/install/entity/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..f77c303
--- /dev/null
+++ b/core/modules/config/tests/config_collection_clash_install_test/config/install/entity/config_test.dynamic.dotted.default.yml
@@ -0,0 +1 @@
+label: entity
diff --git a/core/modules/config/tests/config_collection_clash_install_test/config_collection_clash_install_test.info.yml b/core/modules/config/tests/config_collection_clash_install_test/config_collection_clash_install_test.info.yml
new file mode 100644
index 0000000..8cdab05
--- /dev/null
+++ b/core/modules/config/tests/config_collection_clash_install_test/config_collection_clash_install_test.info.yml
@@ -0,0 +1,9 @@
+# This should contain a copy of the configuration from the
+# config_collection_install_test module.
+name: 'Config collection clash test module'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - config_collection_install_test
diff --git a/core/modules/config/tests/config_existing_default_config_test/config_existing_default_config_test.info.yml b/core/modules/config/tests/config_existing_default_config_test/config_existing_default_config_test.info.yml
deleted file mode 100644
index 75436be..0000000
--- a/core/modules/config/tests/config_existing_default_config_test/config_existing_default_config_test.info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-name: 'Configuration existing default config test'
-type: module
-package: Testing
-version: VERSION
-core: 8.x
diff --git a/core/modules/config/tests/config_install_fail_test/config/install/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_install_fail_test/config/install/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..eb94849
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail_test/config/install/config_test.dynamic.dotted.default.yml
@@ -0,0 +1,7 @@
+# Clashes with default configuration provided by the config_test module.
+id: dotted.default
+label: 'Config install fail'
+weight: 0
+protected_property: Default
+# Intentionally commented out to verify default status behavior.
+# status: 1
diff --git a/core/modules/config/tests/config_install_fail_test/config/install/language/fr/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_install_fail_test/config/install/language/fr/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..e73dec0
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail_test/config/install/language/fr/config_test.dynamic.dotted.default.yml
@@ -0,0 +1,2 @@
+# Clashes with default configuration provided by the config_test module.
+label: 'Je suis'
diff --git a/core/modules/config/tests/config_install_fail_test/config_install_fail_test.info.yml b/core/modules/config/tests/config_install_fail_test/config_install_fail_test.info.yml
new file mode 100644
index 0000000..44a9cf3
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail_test/config_install_fail_test.info.yml
@@ -0,0 +1,7 @@
+name: 'Configuration install fail test'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - config_test
diff --git a/core/modules/field/src/Tests/FieldImportChangeTest.php b/core/modules/field/src/Tests/FieldImportChangeTest.php
index af06824..f2194f7 100644
--- a/core/modules/field/src/Tests/FieldImportChangeTest.php
+++ b/core/modules/field/src/Tests/FieldImportChangeTest.php
@@ -19,6 +19,10 @@ class FieldImportChangeTest extends FieldUnitTestBase {
   /**
    * Modules to enable.
    *
+   * The default configuration provided by field_test_config is imported by
+   * \Drupal\field\Tests\FieldUnitTestBase::setUp() when it installs field
+   * configuration.
+   *
    * @var array
    */
   public static $modules = array('field_test_config');
@@ -31,8 +35,6 @@ function testImportChange() {
     $field_id = "entity_test.entity_test.$field_storage_id";
     $field_config_name = "field.field.$field_id";
 
-    // Import default config.
-    $this->installConfig(array('field_test_config'));
     $active = $this->container->get('config.storage');
     $staging = $this->container->get('config.storage.staging');
     $this->copyConfig($active, $staging);
diff --git a/core/modules/field/src/Tests/FieldImportDeleteTest.php b/core/modules/field/src/Tests/FieldImportDeleteTest.php
index 802d144..030adfb 100644
--- a/core/modules/field/src/Tests/FieldImportDeleteTest.php
+++ b/core/modules/field/src/Tests/FieldImportDeleteTest.php
@@ -21,6 +21,10 @@ class FieldImportDeleteTest extends FieldUnitTestBase {
   /**
    * Modules to enable.
    *
+   * The default configuration provided by field_test_config is imported by
+   * \Drupal\field\Tests\FieldUnitTestBase::setUp() when it installs field
+   * configuration.
+   *
    * @var array
    */
   public static $modules = array('field_test_config');
@@ -53,9 +57,6 @@ public function testImportDelete() {
     // Create a second bundle for the 'Entity test' entity type.
     entity_test_create_bundle('test_bundle');
 
-    // Import default config.
-    $this->installConfig(array('field_test_config'));
-
     // Get the uuid's for the field storages.
     $field_storage_uuid = FieldStorageConfig::load($field_storage_id)->uuid();
     $field_storage_uuid_2 = FieldStorageConfig::load($field_storage_id_2)->uuid();
diff --git a/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml b/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml
index 6ed487b..951e4a3 100644
--- a/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml
+++ b/core/modules/forum/config/install/taxonomy.vocabulary.forums.yml
@@ -1,6 +1,9 @@
 langcode: en
 status: true
-dependencies: {  }
+dependencies:
+  enforced:
+    module:
+      - forum
 name: Forums
 vid: forums
 description: 'Forum navigation vocabulary'
diff --git a/core/modules/system/src/Controller/ThemeController.php b/core/modules/system/src/Controller/ThemeController.php
index 26083cb..7126a7e 100644
--- a/core/modules/system/src/Controller/ThemeController.php
+++ b/core/modules/system/src/Controller/ThemeController.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Controller;
 
 use Drupal\Core\Config\ConfigFactoryInterface;
+use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Routing\RouteBuilderIndicatorInterface;
@@ -120,12 +121,28 @@ public function install(Request $request) {
     $theme = $request->get('theme');
 
     if (isset($theme)) {
-      if ($this->themeHandler->install(array($theme))) {
-        $themes = $this->themeHandler->listInfo();
-        drupal_set_message($this->t('The %theme theme has been installed.', array('%theme' => $themes[$theme]->info['name'])));
+      try {
+        if ($this->themeHandler->install(array($theme))) {
+          $themes = $this->themeHandler->listInfo();
+          drupal_set_message($this->t('The %theme theme has been installed.', array('%theme' => $themes[$theme]->info['name'])));
+        }
+        else {
+          drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
+        }
       }
-      else {
-        drupal_set_message($this->t('The %theme theme was not found.', array('%theme' => $theme)), 'error');
+      catch (PreExistingConfigException $e) {
+        $config_objects = $e->flattenConfigObjects($e->getConfigObjects());
+        drupal_set_message(
+          $this->formatPlural(
+            count($config_objects),
+            'Unable to install @extension, %config_names already exists in active configuration.',
+            'Unable to install @extension, %config_names already exist in active configuration.',
+            array(
+              '%config_names' => implode(', ', $config_objects),
+              '@extension' => $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 24f1b4b..b3c7977 100644
--- a/core/modules/system/src/Form/ModulesListConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesListConfirmForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -157,7 +158,24 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       // the form doesn't allow modules with unmet dependencies, so the only way
       // this can happen is if the filesystem changed between form display and
       // submit, in which case the user has bigger problems.
-      $this->moduleInstaller->install(array_keys($this->modules['install']));
+      try {
+        $this->moduleInstaller->install(array_keys($this->modules['install']));
+      }
+      catch (PreExistingConfigException $e) {
+        $config_objects = $e->flattenConfigObjects($e->getConfigObjects());
+        drupal_set_message(
+          $this->formatPlural(
+            count($config_objects),
+            'Unable to install @extension, %config_names already exists in active configuration.',
+            'Unable to install @extension, %config_names already exist in active configuration.',
+            array(
+              '%config_names' => implode(', ', $config_objects),
+              '@extension' => $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 2486ca4..2e80482 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Controller\TitleResolverInterface;
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -517,7 +518,24 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
 
     // There seem to be no dependencies that would need approval.
     if (!empty($modules['install'])) {
-      $this->moduleInstaller->install(array_keys($modules['install']));
+      try {
+        $this->moduleInstaller->install(array_keys($modules['install']));
+      }
+      catch (PreExistingConfigException $e) {
+        $config_objects = $e->flattenConfigObjects($e->getConfigObjects());
+        drupal_set_message(
+          $this->formatPlural(
+            count($config_objects),
+            'Unable to install @extension, %config_names already exists in active configuration.',
+            'Unable to install @extension, %config_names already exist in active configuration.',
+            array(
+              '%config_names' => implode(', ', $config_objects),
+              '@extension' => $modules['install'][$e->getExtension()]
+            )),
+          'error'
+        );
+        return;
+      }
     }
 
     // Gets module list after install process, flushes caches and displays a
