diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index fb18fe3..db35fd7 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -6,7 +6,6 @@
 use Drupal\Core\Config\BootstrapConfigStorageFactory;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\DatabaseExceptionWrapper;
-use Drupal\Core\Database\Install\TaskException;
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Installer\Exception\AlreadyInstalledException;
 use Drupal\Core\Installer\Exception\InstallerException;
@@ -1133,14 +1132,24 @@ function install_database_errors($database, $settings_file) {
     // Run tasks associated with the database type. Any errors are caught in the
     // calling function.
     Database::addConnectionInfo('default', 'default', $database);
-    try {
-      db_run_tasks($driver);
-    }
-    catch (TaskException $e) {
+
+    $errors = db_installer_object($driver)->runTasks();
+    if (count($errors)) {
+      $error_message = [
+        '#type' => 'inline_template',
+        '#template' => '{% trans %}Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/getting-started/install">installation handbook</a>, or contact your hosting provider.{% endtrans%}{{ errors }}',
+        '#context' => [
+          'errors' => [
+            '#theme' => 'item_list',
+            '#items' => $errors,
+          ],
+        ],
+      ];
+
       // These are generic errors, so we do not have any specific key of the
       // database connection array to attach them to; therefore, we just put
       // them in the error array with standard numeric keys.
-      $errors[$driver . '][0'] = $e->getMessage();
+      $errors[$driver . '][0'] = \Drupal::service('renderer')->renderPlain($error_message);
     }
   }
   return $errors;
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 31d472a..77e0b70 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -1069,19 +1069,6 @@ function install_profile_info($profile, $langcode = 'en') {
 }
 
 /**
- * Ensures the environment for a Drupal database on a predefined connection.
- *
- * This will run tasks that check that Drupal can perform all of the functions
- * on a database, that Drupal needs. Tasks include simple checks like CREATE
- * TABLE to database specific functions like stored procedures and client
- * encoding.
- */
-function db_run_tasks($driver) {
-  db_installer_object($driver)->runTasks();
-  return TRUE;
-}
-
-/**
  * Returns a database installer object.
  *
  * @param $driver
diff --git a/core/lib/Drupal/Core/Database/Install/TaskException.php b/core/lib/Drupal/Core/Database/Install/TaskException.php
deleted file mode 100644
index cbf5c1a..0000000
--- a/core/lib/Drupal/Core/Database/Install/TaskException.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\Core\Database\Install\TaskException.
- */
-
-namespace Drupal\Core\Database\Install;
-
-/**
- * Exception thrown if the database installer fails.
- */
-class TaskException extends \RuntimeException { }
diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php
index ee9c23e..9ca41c3 100644
--- a/core/lib/Drupal/Core/Database/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Install/Tasks.php
@@ -128,6 +128,9 @@ public function minimumVersion() {
 
   /**
    * Run database tasks and tests to see if Drupal can run on the database.
+   *
+   * @return array
+   *   A list of error messages.
    */
   public function runTasks() {
     // We need to establish a connection before we can run tests.
@@ -143,21 +146,15 @@ public function runTasks() {
           }
         }
         else {
-          throw new TaskException(t("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
+          $this->fail(t("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
         }
       }
     }
-    // Check for failed results and compile message
-    $message = '';
-    foreach ($this->results as $result => $success) {
-      if (!$success) {
-        $message = SafeMarkup::isSafe($result) ? $result : SafeMarkup::checkPlain($result);
-      }
-    }
-    if (!empty($message)) {
-      $message = SafeMarkup::set('Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/getting-started/install">installation handbook</a>, or contact your hosting provider.' . $message);
-      throw new TaskException($message);
-    }
+    // Filter out the success messages from results.
+    $errors = array_filter($this->results, function ($value) {
+      return !$value;
+    });
+    return array_keys($errors);
   }
 
   /**
diff --git a/core/modules/simpletest/src/InstallerTestBase.php b/core/modules/simpletest/src/InstallerTestBase.php
index c340c92..7207555 100644
--- a/core/modules/simpletest/src/InstallerTestBase.php
+++ b/core/modules/simpletest/src/InstallerTestBase.php
@@ -138,33 +138,33 @@ protected function setUp() {
     // Configure site.
     $this->setUpSite();
 
-    // Import new settings.php written by the installer.
-    $request = Request::createFromGlobals();
-    $class_loader = require $this->container->get('app.root') . '/autoload.php';
-    Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
-    foreach ($GLOBALS['config_directories'] as $type => $path) {
-      $this->configDirectories[$type] = $path;
+    if ($this->isInstalled) {
+      // Import new settings.php written by the installer.
+      $request = Request::createFromGlobals();
+      $class_loader = require $this->container->get('app.root') . '/autoload.php';
+      Settings::initialize($this->container->get('app.root'), DrupalKernel::findSitePath($request), $class_loader);
+      foreach ($GLOBALS['config_directories'] as $type => $path) {
+        $this->configDirectories[$type] = $path;
+      }
+
+      // After writing settings.php, the installer removes write permissions
+      // from the site directory. To allow drupal_generate_test_ua() to write
+      // a file containing the private key for drupal_valid_test_ua(), the site
+      // directory has to be writable.
+      // WebTestBase::tearDown() will delete the entire test site directory.
+      // Not using File API; a potential error must trigger a PHP warning.
+      chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
+      $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
+      $this->kernel->prepareLegacyRequest($request);
+      $this->container = $this->kernel->getContainer();
+
+      // Manually configure the test mail collector implementation to prevent
+      // tests from sending out e-mails and collect them in state instead.
+      $this->container->get('config.factory')
+        ->getEditable('system.mail')
+        ->set('interface.default', 'test_mail_collector')
+        ->save();
     }
-
-    // After writing settings.php, the installer removes write permissions
-    // from the site directory. To allow drupal_generate_test_ua() to write
-    // a file containing the private key for drupal_valid_test_ua(), the site
-    // directory has to be writable.
-    // WebTestBase::tearDown() will delete the entire test site directory.
-    // Not using File API; a potential error must trigger a PHP warning.
-    chmod($this->container->get('app.root') . '/' . $this->siteDirectory, 0777);
-    $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE);
-    $this->kernel->prepareLegacyRequest($request);
-    $this->container = $this->kernel->getContainer();
-    $config = $this->container->get('config.factory');
-
-    // Manually configure the test mail collector implementation to prevent
-    // tests from sending out e-mails and collect them in state instead.
-    $config->getEditable('system.mail')
-      ->set('interface.default', 'test_mail_collector')
-      ->save();
-
-    $this->isInstalled = TRUE;
   }
 
   /**
@@ -196,11 +196,14 @@ protected function setUpSettings() {
   }
 
   /**
-   * Installer step: Configure site.
+   * Final installer step: Configure site.
    */
   protected function setUpSite() {
     $edit = $this->translatePostValues($this->parameters['forms']['install_configure_form']);
     $this->drupalPostForm(NULL, $edit, $this->translations['Save and continue']);
+    // If we've got to this point the site is installed using the regular
+    // installation workflow.
+    $this->isInstalled = TRUE;
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php b/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php
new file mode 100644
index 0000000..2452c40
--- /dev/null
+++ b/core/modules/system/src/Tests/Installer/InstallerDatabaseErrorMessagesTest.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Installer\InstallerDatabaseErrorMessagesTest.
+ */
+
+namespace Drupal\system\Tests\Installer;
+
+use Drupal\Core\Database\Database;
+use Drupal\simpletest\InstallerTestBase;
+
+/**
+ * Tests the installer with database errors.
+ *
+ * @group Installer
+ */
+class InstallerDatabaseErrorMessagesTest extends InstallerTestBase {
+
+  /**
+   * @{inheritdoc}
+   */
+  protected function setUpSettings() {
+    // We are creating a table here to force an error in the installer because
+    // it will try and create the drupal_install_test table as this is part of
+    // the standard database tests performed by the installer in
+    // Drupal\Core\Database\Install\Tasks.
+    Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)');
+    parent::setUpSettings();
+  }
+
+  /**
+   * @{inheritdoc}
+   */
+  protected function setUpSite() {
+    // This step should not appear as we had a failure on the settings screen.
+  }
+
+  /**
+   * Verifies that the error message in the settings step is correct.
+   */
+  public function testSetUpSettingsErrorMessage() {
+    $this->assertRaw('<ul><li>Failed to <strong>CREATE</strong> a test table');
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
index b0e6597..a662428 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Tests\Installer;
 
+use Drupal\Core\Database\Database;
 use Drupal\simpletest\InstallerTestBase;
 use Drupal\user\Entity\User;
 
@@ -46,6 +47,26 @@ protected function setUpLanguage() {
   }
 
   /**
+   * @{inheritdoc}
+   */
+  protected function setUpSettings() {
+    // We are creating a table here to force an error in the installer because
+    // it will try and create the drupal_install_test table as this is part of
+    // the standard database tests performed by the installer in
+    // Drupal\Core\Database\Install\Tasks.
+    Database::getConnection('default')->query('CREATE TABLE {drupal_install_test} (id int NULL)');
+    parent::setUpSettings();
+
+    // Ensure that the error message translation is working.
+    $this->assertRaw('Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der <a href="https://www.drupal.org/getting-started/install">Installationshandbuch</a>, oder kontaktieren Sie Ihren Hosting-Anbieter.');
+    $this->assertRaw('<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl <em class="placeholder">CREATE TABLE {drupal_install_test} (id int NULL)</em> fehlgeschlagen.');
+
+    // Now do it successfully.
+    Database::getConnection('default')->query('DROP TABLE {drupal_install_test}');
+    parent::setUpSettings();
+  }
+
+  /**
    * Verifies the expected behaviors of the installation result.
    */
   public function testInstaller() {
@@ -127,6 +148,12 @@ protected function getPo($langcode) {
 
 msgid "Anonymous"
 msgstr "Anonymous $langcode"
+
+msgid "Resolve all issues below to continue the installation. For help configuring your database server, see the <a href="https://www.drupal.org/getting-started/install">installation handbook</a>, or contact your hosting provider."
+msgstr "Beheben Sie alle Probleme unten, um die Installation fortzusetzen. Informationen zur Konfiguration der Datenbankserver finden Sie in der <a href="https://www.drupal.org/getting-started/install">Installationshandbuch</a>, oder kontaktieren Sie Ihren Hosting-Anbieter."
+
+msgid "Failed to <strong>CREATE</strong> a test table on your database server with the command %query. The server reports the following message: %error.<p>Are you sure the configured username has the necessary permissions to create tables in the database?</p>"
+msgstr "<strong>CREATE</strong> ein Test-Tabelle auf Ihrem Datenbankserver mit dem Befehl %query fehlgeschlagen."
 ENDPO;
   }
 
