diff --git a/core/lib/Drupal/Core/Controller/ExceptionController.php b/core/lib/Drupal/Core/Controller/ExceptionController.php
index c8da4bc38fd243aa7e65deb51b312967718ad02f..d79567c3ba938610a91e73e10df465721ae14bb6 100644
--- a/core/lib/Drupal/Core/Controller/ExceptionController.php
+++ b/core/lib/Drupal/Core/Controller/ExceptionController.php
@@ -317,13 +317,40 @@ public function on500Html(FlattenException $exception, Request $request) {
       $class = 'error';
 
       // If error type is 'User notice' then treat it as debug information
-      // instead of an error message, see dd().
+      // instead of an error message.
+      // @see debug()
       if ($error['%type'] == 'User notice') {
         $error['%type'] = 'Debug';
         $class = 'status';
       }
 
-      drupal_set_message(t('%type: !message in %function (line %line of %file).', $error), $class);
+      // Attempt to reduce verbosity by removing DRUPAL_ROOT from the file path
+      // in the message. This does not happen for (false) security.
+      $root_length = strlen(DRUPAL_ROOT);
+      if (substr($error['%file'], 0, $root_length) == DRUPAL_ROOT) {
+        $error['%file'] = substr($error['%file'], $root_length + 1);
+      }
+      // Should not translate the string to avoid errors producing more errors.
+      $message = String::format('%type: !message in %function (line %line of %file).', $error);
+
+      // Check if verbose error reporting is on.
+      $error_level = $this->container->get('config.factory')->get('system.logging')->get('error_level');
+
+      if ($error_level == ERROR_REPORTING_DISPLAY_VERBOSE) {
+        $backtrace_exception = $exception;
+        while ($backtrace_exception->getPrevious()) {
+          $backtrace_exception = $backtrace_exception->getPrevious();
+        }
+        $backtrace = $backtrace_exception->getTrace();
+        // First trace is the error itself, already contained in the message.
+        // While the second trace is the error source and also contained in the
+        // message, the message doesn't contain argument values, so we output it
+        // once more in the backtrace.
+        array_shift($backtrace);
+        // Generate a backtrace containing only scalar argument values.
+        $message .= '<pre class="backtrace">' . Error::formatFlattenedBacktrace($backtrace) . '</pre>';
+      }
+      drupal_set_message($message, $class, TRUE);
     }
 
     $page_content = array(
diff --git a/core/lib/Drupal/Core/Utility/Error.php b/core/lib/Drupal/Core/Utility/Error.php
index 669cca03a89d9b0f4f6eebfd83611380b7b32e2a..e3b084f15f8ef90a0aded259fa08e468cf9fefea 100644
--- a/core/lib/Drupal/Core/Utility/Error.php
+++ b/core/lib/Drupal/Core/Utility/Error.php
@@ -185,4 +185,56 @@ public static function formatBacktrace(array $backtrace) {
     return $return;
   }
 
+  /**
+   * Formats a flattened backtrace into a plain-text string.
+   *
+   * The calls show values for scalar arguments and type names for complex ones.
+   *
+   * @param array $backtrace
+   *   The backtrace of a Symfony\Component\Debug\Exception\FlattenException.
+   *
+   * @return string
+   *   A plain-text line-wrapped string ready to be put inside <pre>.
+   */
+  public static function formatFlattenedBacktrace(array $backtrace) {
+    $return = '';
+
+    foreach ($backtrace as $trace) {
+      $call = array('function' => '', 'args' => array());
+
+      if (isset($trace['class'])) {
+        $call['function'] = $trace['class'] . $trace['type'] . $trace['function'];
+      }
+      elseif (isset($trace['function'])) {
+        $call['function'] = $trace['function'];
+      }
+      else {
+        $call['function'] = 'main';
+      }
+
+      if (isset($trace['args'])) {
+        foreach ($trace['args'] as $arg) {
+          $type = $arg[0];
+          $value = $arg[1];
+          if ($type == 'array') {
+            $call['args'][] = '[' . ucfirst($type) . ']';
+          }
+          elseif ($type == 'null') {
+            $call['args'][] = strtoupper($type);
+          }
+          elseif ($type == 'boolean') {
+            $call['args'][] = $value ? 'TRUE' : 'FALSE';
+          }
+          else {
+            $call['args'][] = $value;
+          }
+        }
+      }
+
+      $return .= $call['function'] . '(' . implode(', ', $call['args']) . ")\n";
+    }
+
+    return $return;
+  }
+
 }