diff --git a/core/core.services.yml b/core/core.services.yml
index 3f68677200..0d5ea4a312 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1672,7 +1672,7 @@ services:
       - { name: event_subscriber }
   messenger:
     class: Drupal\Core\Messenger\Messenger
-    arguments: ['@session.flash_bag', '@page_cache_kill_switch']
+    arguments: ['@session', '@page_cache_kill_switch']
   tempstore.private:
     class: Drupal\Core\TempStore\PrivateTempStoreFactory
     arguments: ['@keyvalue.expirable', '@lock', '@current_user', '@request_stack', '%tempstore.expire%']
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index b4c731da3c..2360d32e7e 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -33,6 +33,7 @@
 use Symfony\Component\Routing\Route;
 use Drupal\user\Entity\User;
 use GuzzleHttp\Exception\RequestException;
+use Drupal\Core\Messenger\NullMessenger;
 
 /**
  * Do not run the task during the current installation request.
@@ -975,6 +976,11 @@ function install_display_output($output, $install_state) {
   // reached in case of an early installer error.
   drupal_maintenance_theme();
 
+  // Override the messenger service if a database connection hasn't been set up.
+  if (!in_array('install_base_system', $install_state['tasks_performed'])) {
+    \Drupal::getContainer()->set('messenger', new NullMessenger());
+  }
+
   // Prevent install.php from being indexed when installed in a sub folder.
   // robots.txt rules are not read if the site is within domain.com/subfolder
   // resulting in /subfolder/install.php being found through search engines.
diff --git a/core/lib/Drupal/Core/Messenger/Messenger.php b/core/lib/Drupal/Core/Messenger/Messenger.php
index c0949438cc..47244a8c3f 100644
--- a/core/lib/Drupal/Core/Messenger/Messenger.php
+++ b/core/lib/Drupal/Core/Messenger/Messenger.php
@@ -5,7 +5,7 @@
 use Drupal\Component\Render\MarkupInterface;
 use Drupal\Core\PageCache\ResponsePolicy\KillSwitch;
 use Drupal\Core\Render\Markup;
-use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
 
 /**
  * The messenger service.
@@ -13,11 +13,11 @@
 class Messenger implements MessengerInterface {
 
   /**
-   * The flash bag.
+   * The session.
    *
-   * @var \Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface
+   * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
    */
-  protected $flashBag;
+  protected $session;
 
   /**
    * The kill switch.
@@ -29,16 +29,26 @@ class Messenger implements MessengerInterface {
   /**
    * Messenger constructor.
    *
-   * @param \Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface $flash_bag
-   *   The flash bag.
+   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
+   *   The session.
    * @param \Drupal\Core\PageCache\ResponsePolicy\KillSwitch $killSwitch
    *   The kill switch.
    */
-  public function __construct(FlashBagInterface $flash_bag, KillSwitch $killSwitch) {
-    $this->flashBag = $flash_bag;
+  public function __construct(SessionInterface $session, KillSwitch $killSwitch) {
+    $this->session = $session;
     $this->killSwitch = $killSwitch;
   }
 
+  /**
+   * Gets the flash bag.
+   *
+   * @return \Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface
+   *   The flash bag.
+   */
+  private function getFlashBag() {
+    return $this->session->getFlashBag();
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -56,8 +66,8 @@ public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE)
 
     // Do not use strict type checking so that equivalent string and
     // MarkupInterface objects are detected.
-    if ($repeat || !in_array($message, $this->flashBag->peek($type))) {
-      $this->flashBag->add($type, $message);
+    if ($repeat || !in_array($message, $this->getFlashBag()->peek($type))) {
+      $this->getFlashBag()->add($type, $message);
     }
 
     // Mark this page as being uncacheable.
@@ -84,14 +94,14 @@ public function addWarning($message, $repeat = FALSE) {
    * {@inheritdoc}
    */
   public function all() {
-    return $this->flashBag->peekAll();
+    return $this->getFlashBag()->peekAll();
   }
 
   /**
    * {@inheritdoc}
    */
   public function deleteAll() {
-    return $this->flashBag->clear();
+    return $this->getFlashBag()->clear();
   }
 
   /**
@@ -99,14 +109,14 @@ public function deleteAll() {
    */
   public function deleteByType($type) {
     // Flash bag gets and clears flash messages from the stack.
-    return $this->flashBag->get($type);
+    return $this->getFlashBag()->get($type);
   }
 
   /**
    * {@inheritdoc}
    */
   public function messagesByType($type) {
-    return $this->flashBag->peek($type);
+    return $this->getFlashBag()->peek($type);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Messenger/NullMessenger.php b/core/lib/Drupal/Core/Messenger/NullMessenger.php
new file mode 100644
index 0000000000..111162ed98
--- /dev/null
+++ b/core/lib/Drupal/Core/Messenger/NullMessenger.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Drupal\Core\Messenger;
+
+/**
+ * Defines a stub messenger.
+ *
+ * The stub implementation is needed for rendering during installation.
+ */
+class NullMessenger implements MessengerInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addError($message, $repeat = FALSE) {
+    return $this->addMessage($message, static::TYPE_ERROR, $repeat);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addMessage($message, $type = self::TYPE_STATUS, $repeat = FALSE) {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addStatus($message, $repeat = FALSE) {
+    return $this->addMessage($message, static::TYPE_STATUS, $repeat);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addWarning($message, $repeat = FALSE) {
+    return $this->addMessage($message, static::TYPE_WARNING, $repeat);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function all() {
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteAll() {
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteByType($type) {
+    // Flash bag gets and clears flash messages from the stack.
+    return [];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function messagesByType($type) {
+    return [];
+  }
+
+}
