diff --git a/core/core.services.yml b/core/core.services.yml
index 08bec38..3e4fa11 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -291,7 +291,14 @@ services:
     arguments: ['@app.root', '%container.modules%', '@cache.bootstrap']
   module_installer:
     class: Drupal\Core\Extension\ModuleInstaller
+    tags:
+      - { name: service_collector, tag: 'module_install.uninstall_validator', call: addUninstallValidator }
     arguments: ['@app.root', '@module_handler', '@kernel']
+  content_uninstall_validator:
+    class: Drupal\Core\Entity\ContentUninstallValidator
+    tags:
+      - { name: module_install.uninstall_validator, priority: -254 }
+    arguments: ['@entity.manager', '@entity.query']
   theme_handler:
     class: Drupal\Core\Extension\ThemeHandler
     arguments: ['@app.root', '@config.factory', '@module_handler', '@state', '@info_parser', '@logger.channel.default', '@asset.css.collection_optimizer', '@config.installer', '@config.manager', '@router.builder_indicator']
diff --git a/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php b/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php
new file mode 100644
index 0000000..d68e113
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/ContentUninstallValidator.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Core\Entity\ContentUninstallValidator.
+ */
+
+namespace Drupal\Core\Entity;
+
+use Drupal\Core\Extension\UninstallValidatorInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+
+/**
+ * Validates module uninstall readiness based on existing content entities.
+ */
+class ContentUninstallValidator implements UninstallValidatorInterface {
+
+  /**
+   * Constructs a new ContentUninstallValidator.
+   *
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query
+   *   The entity query factory.
+   */
+  public function __construct(EntityManagerInterface $entity_manager, QueryFactory $entity_query) {
+    $this->entityManager = $entity_manager;
+    $this->queryFactory = $entity_query;
+  }
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($module) {
+    $entities = $this->entityManager->getDefinitions();
+    foreach ($entities as $entity_type) {
+      if ($module == $entity_type->getProvider() && is_subclass_of($entity_type->getClass(), 'Drupal\Core\Entity\ContentEntityInterface') && $entity_type->getBaseTable()) {
+        $content = $this->queryFactory->get($entity_type->id())
+          ->accessCheck(FALSE)
+          ->range(0, 1)
+          ->execute();
+        if (!empty($content)) {
+          return FALSE;
+        }
+      }
+    }
+    return TRUE;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 20a6506..daae5e6 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\DrupalKernelInterface;
+use Drupal\Core\Extension\UninstallValidatorInterface;
 
 /**
  * Default implementation of the module installer.
@@ -42,6 +43,20 @@ class ModuleInstaller implements ModuleInstallerInterface {
   protected $root;
 
   /**
+   * The uninstall validators.
+   *
+   * @var \Drupal\Core\Extension\UninstallValidatorInterface[]
+   */
+  protected $uninstallValidators;
+
+  /**
+   * Modules that can be uninstalled.
+   *
+   * @var array
+   */
+  protected $uninstallValidated;
+
+  /**
    * Constructs a new ModuleInstaller instance.
    *
    * @param string $root
@@ -58,6 +73,14 @@ public function __construct($root, ModuleHandlerInterface $module_handler, Drupa
     $this->root = $root;
     $this->moduleHandler = $module_handler;
     $this->kernel = $kernel;
+    $this->uninstallValidated = array();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addUninstallValidator(UninstallValidatorInterface $uninstall_validator) {
+    $this->uninstallValidators[] = $uninstall_validator;
   }
 
   /**
@@ -271,6 +294,7 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
    * {@inheritdoc}
    */
   public function uninstall(array $module_list, $uninstall_dependents = TRUE) {
+    $module_list = $this->validateUninstall($module_list);
     // Get all module data so we can find dependencies and sort.
     $module_data = system_rebuild_module_data();
     $module_list = $module_list ? array_combine($module_list, $module_list) : array();
@@ -469,4 +493,25 @@ protected function updateKernel($module_filenames) {
     $this->moduleHandler = $container->get('module_handler');
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function validateUninstall(array $module_list) {
+    foreach ($module_list as $key => $module) {
+      if (in_array($module, $this->uninstallValidated)) {
+        continue;
+      }
+      foreach ($this->uninstallValidators as $validator) {
+        if ($validator->validate($module)) {
+          $this->uninstallValidated[] = $module;
+        }
+        else {
+          unset($module_list[$key]);
+        }
+      }
+    }
+    return $module_list;
+  }
+
+
 }
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php b/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php
index 246af4b..0d29dce 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstallerInterface.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core\Extension;
 
+use Drupal\Core\Extension\UninstallValidatorInterface;
+
 /**
  * Provides the installation of modules with creating the db schema and more.
  */
@@ -58,5 +60,22 @@ public function install(array $module_list, $enable_dependencies = TRUE);
    */
   public function uninstall(array $module_list, $uninstall_dependents = TRUE);
 
+  /**
+   * Adds module uninstall validator services.
+   *
+   * @param \Drupal\Core\Extension\UninstallValidatorInterface $uninstall_validator
+   *   The uninstall validation service to add. It is added at the end of the
+   *   priority list (lower priority relative to existing ones).
+   */
+  public function addUninstallValidator(UninstallValidatorInterface $uninstall_validator);
+
+  /**
+   * Determines which modules can be uninstalled.
+   *
+   * @param array $module_list
+   *   The modules to uninstall.
+   */
+  public function validateUninstall(array $module_list);
+
 }
 
diff --git a/core/lib/Drupal/Core/Extension/UninstallValidatorInterface.php b/core/lib/Drupal/Core/Extension/UninstallValidatorInterface.php
new file mode 100644
index 0000000..aa3a403
--- /dev/null
+++ b/core/lib/Drupal/Core/Extension/UninstallValidatorInterface.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @file
+ * Contains Drupal\Core\Extension\UninstallValidatorInterface.
+ */
+
+namespace Drupal\Core\Extension;
+
+/**
+ * Common interface for module uninstall validators.
+ */
+interface UninstallValidatorInterface {
+
+  /**
+   * Determines if a module may be uninstalled.
+   *
+   * @param string $module
+   *   A module name.
+   *
+   * @return bool
+   *   TRUE if the module is ready to be uninstalled.
+   */
+  public function validate($module);
+}
diff --git a/core/modules/config/src/Tests/ConfigImportAllTest.php b/core/modules/config/src/Tests/ConfigImportAllTest.php
index b620ad8..a7ce00d 100644
--- a/core/modules/config/src/Tests/ConfigImportAllTest.php
+++ b/core/modules/config/src/Tests/ConfigImportAllTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Config\StorageComparer;
 use Drupal\system\Tests\Module\ModuleTestBase;
+use Drupal\shortcut\Entity\Shortcut;
 
 /**
  * Tests the largest configuration import possible with the modules and profiles
@@ -83,6 +84,10 @@ public function testInstallUninstall() {
       $term->delete();
     }
 
+    // Delete any shortcuts so the shortcut module can be uninstalled.
+    $shortcuts = Shortcut::loadMultiple();
+    entity_delete_multiple('shortcut', array_keys($shortcuts));
+
     system_list_reset();
     $all_modules = system_rebuild_module_data();
 
diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php
index 4285956..bc6fcf0 100644
--- a/core/modules/system/src/Form/ModulesUninstallForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Form;
 
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
@@ -26,6 +27,13 @@ class ModulesUninstallForm extends FormBase {
   protected $moduleHandler;
 
   /**
+   * The module installer service.
+   *
+   * @var \Drupal\Core\Extension\ModuleInstallerInterface
+   */
+  protected $moduleInstaller;
+
+  /**
    * The expirable key value store.
    *
    * @var \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface
@@ -38,6 +46,7 @@ class ModulesUninstallForm extends FormBase {
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('module_handler'),
+      $container->get('module_installer'),
       $container->get('keyvalue.expirable')->get('modules_uninstall')
     );
   }
@@ -47,11 +56,14 @@ public static function create(ContainerInterface $container) {
    *
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
+   * @param \Drupal\Core\Extension\ModuleInstallerInterface $module_installer
+   *   The module installer.
    * @param \Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface $key_value_expirable
    *   The key value expirable factory.
    */
-  public function __construct(ModuleHandlerInterface $module_handler, KeyValueStoreExpirableInterface $key_value_expirable) {
+  public function __construct(ModuleHandlerInterface $module_handler, ModuleInstallerInterface $module_installer, KeyValueStoreExpirableInterface $key_value_expirable) {
     $this->moduleHandler = $module_handler;
+    $this->moduleInstaller = $module_installer;
     $this->keyValueExpirable = $key_value_expirable;
   }
 
@@ -71,8 +83,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     // Get a list of disabled, installed modules.
     $modules = system_rebuild_module_data();
-    $uninstallable = array_filter($modules, function ($module) use ($modules) {
-      return empty($modules[$module->getName()]->info['required']) && drupal_get_installed_schema_version($module->getName()) > SCHEMA_UNINSTALLED;
+    $modules_validated = $this->moduleInstaller->validateUninstall(array_keys($modules));
+    $uninstallable = array_filter($modules, function ($module) use ($modules, $modules_validated) {
+      return empty($modules[$module->getName()]->info['required']) && drupal_get_installed_schema_version($module->getName()) > SCHEMA_UNINSTALLED && in_array($module->getName(), $modules_validated);
     });
 
     // Include system.admin.inc so we can use the sort callbacks.
