 .../EventSubscriber/DefaultExceptionSubscriber.php | 100 ++++++++-------------
 .../Comment/CommentResourceTestBase.php            |   2 +-
 .../DefaultExceptionSubscriberTest.php             |  22 ++++-
 3 files changed, 57 insertions(+), 67 deletions(-)

diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
index 7b5ecc1..4d3bffc 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
@@ -7,7 +7,6 @@
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Utility\Error;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
@@ -59,19 +58,19 @@ protected function getErrorLevel() {
   }
 
   /**
-   * Handles any exception as a generic error page for HTML.
+   * Handles exceptions for this subscriber.
    *
    * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
    *   The event to process.
    */
-  protected function onHtml(GetResponseForExceptionEvent $event) {
+  public function onException(GetResponseForExceptionEvent $event) {
     $exception = $event->getException();
     $error = Error::decodeException($exception);
 
     // Display the message if the current error reporting level allows this type
     // of message to be displayed, and unconditionally in update.php.
     $message = '';
-    if (error_displayable($error)) {
+    if ($this->isErrorDisplayable($error)) {
       // If error type is 'User notice' then treat it as debug information
       // instead of an error message.
       // @see debug()
@@ -79,16 +78,11 @@ protected function onHtml(GetResponseForExceptionEvent $event) {
         $error['%type'] = 'Debug';
       }
 
-      // 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);
-      }
+      $error = $this->simplifyFileInError($error);
 
       unset($error['backtrace']);
 
-      if ($this->getErrorLevel() != ERROR_REPORTING_DISPLAY_VERBOSE) {
+      if (!$this->isErrorLevelVerbose()) {
         // Without verbose logging, use a simple message.
 
         // We call SafeMarkup::format directly here, rather than use t() since
@@ -132,75 +126,55 @@ protected function onHtml(GetResponseForExceptionEvent $event) {
   }
 
   /**
-   * Handles an HttpExceptionInterface exception for unknown formats.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
-   *   The event to process.
+   * {@inheritdoc}
    */
-  protected function onFormatUnknown(GetResponseForExceptionEvent $event) {
-    /** @var \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface|\Exception $exception */
-    $exception = $event->getException();
-
-    $response = new Response($exception->getMessage(), $exception->getStatusCode(), $exception->getHeaders());
-    $event->setResponse($response);
+  public static function getSubscribedEvents() {
+    $events[KernelEvents::EXCEPTION][] = ['onException', -256];
+    return $events;
   }
 
   /**
-   * Handles errors for this subscriber.
+   * Checks whether the error level is verbose or not.
    *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
-   *   The event to process.
+   * @return bool
    */
-  public function onException(GetResponseForExceptionEvent $event) {
-    $format = $this->getFormat($event->getRequest());
-    $exception = $event->getException();
-
-    $method = 'on' . $format;
-    if (!method_exists($this, $method)) {
-      if ($exception instanceof HttpExceptionInterface) {
-        $this->onFormatUnknown($event);
-        $response = $event->getResponse();
-        $response->headers->set('Content-Type', 'text/plain');
-      }
-      else {
-        $this->onHtml($event);
-      }
-    }
-    else {
-      $this->$method($event);
-    }
+  protected function isErrorLevelVerbose() {
+    return $this->getErrorLevel() != ERROR_REPORTING_DISPLAY_VERBOSE;
   }
 
   /**
-   * Gets the error-relevant format from the request.
+   * Wrapper for error_displayable().
    *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The request object.
+   * @param $error
+   *   Optional error to examine for ERROR_REPORTING_DISPLAY_SOME.
    *
-   * @return string
-   *   The format as which to treat the exception.
+   * @return bool
+   *
+   * @see \error_displayable
    */
-  protected function getFormat(Request $request) {
-    $format = $request->query->get(MainContentViewSubscriber::WRAPPER_FORMAT, $request->getRequestFormat());
-
-    // These are all JSON errors for our purposes. Any special handling for
-    // them can/should happen in earlier listeners if desired.
-    if (in_array($format, ['drupal_modal', 'drupal_dialog', 'drupal_ajax'])) {
-      $format = 'json';
-    }
-
-    return $format;
+  protected function isErrorDisplayable($error) {
+    return error_displayable($error);
   }
 
   /**
-   * Registers the methods in this class that should be listeners.
+   * Attempts to reduce error verbosity in the error message's file path.
+   *
+   * Attempts to reduce verbosity by removing DRUPAL_ROOT from the file path in
+   * the message. This does not happen for (false) security.
+   *
+   * @param $error
+   *   Optional error to examine for ERROR_REPORTING_DISPLAY_SOME.
    *
-   * @return array
-   *   An array of event listener definitions.
+   * @return
+   *   The updated $error.
    */
-  public static function getSubscribedEvents() {
-    $events[KernelEvents::EXCEPTION][] = ['onException', -256];
-    return $events;
+  protected function simplifyFileInError($error) {
+    // 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);
+    }
   }
 
 }
diff --git a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
index b04da54..223a1ee 100644
--- a/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
+++ b/core/modules/rest/tests/src/Functional/EntityResource/Comment/CommentResourceTestBase.php
@@ -281,7 +281,7 @@ public function testPostDxWithoutCriticalBaseFields() {
     // @todo Uncomment, remove next 3 lines in https://www.drupal.org/node/2820364.
     $this->assertSame(500, $response->getStatusCode());
     $this->assertSame(['text/plain; charset=UTF-8'], $response->getHeader('Content-Type'));
-    $this->assertSame('Internal Server Error', (string) $response->getBody());
+    $this->assertStringStartsWith('The website encountered an unexpected error. Please try again later.</br></br><em class="placeholder">Symfony\Component\HttpKernel\Exception\HttpException</em>: Internal Server Error in <em class="placeholder">Drupal\rest\Plugin\rest\resource\EntityResource-&gt;post()</em>', (string) $response->getBody());
     //$this->assertResourceErrorResponse(422, "Unprocessable Entity: validation failed.\nentity_type: This value should not be null.\n", $response);
 
     // DX: 422 when missing 'entity_id' field.
diff --git a/core/tests/Drupal/Tests/Core/EventSubscriber/DefaultExceptionSubscriberTest.php b/core/tests/Drupal/Tests/Core/EventSubscriber/DefaultExceptionSubscriberTest.php
index 6582500..a0a48a1 100644
--- a/core/tests/Drupal/Tests/Core/EventSubscriber/DefaultExceptionSubscriberTest.php
+++ b/core/tests/Drupal/Tests/Core/EventSubscriber/DefaultExceptionSubscriberTest.php
@@ -18,7 +18,6 @@ class DefaultExceptionSubscriberTest extends UnitTestCase {
 
   /**
    * @covers ::onException
-   * @covers ::onFormatUnknown
    */
   public function testOnExceptionWithUnknownFormat() {
     $config_factory = $this->getConfigFactoryStub();
@@ -27,12 +26,13 @@ public function testOnExceptionWithUnknownFormat() {
     $request = Request::create('/test?_format=bananas');
     $e = new MethodNotAllowedHttpException(['POST', 'PUT'], 'test message');
     $event = new GetResponseForExceptionEvent($kernel->reveal(), $request, 'GET', $e);
-    $subscriber = new DefaultExceptionSubscriber($config_factory);
+    $subscriber = new TestDefaultExceptionSubscriber($config_factory);
+    $subscriber->setStringTranslation($this->getStringTranslationStub());
     $subscriber->onException($event);
     $response = $event->getResponse();
 
     $this->assertInstanceOf(Response::class, $response);
-    $this->assertEquals('test message', $response->getContent());
+    $this->stringStartsWith('The website encountered an unexpected error. Please try again later.</br></br><em class="placeholder">Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException</em>: test message in ', $response->getContent());
     $this->assertEquals(405, $response->getStatusCode());
     $this->assertEquals('POST, PUT', $response->headers->get('Allow'));
     // Also check that that text/plain content type was added.
@@ -40,3 +40,19 @@ public function testOnExceptionWithUnknownFormat() {
   }
 
 }
+
+class TestDefaultExceptionSubscriber extends DefaultExceptionSubscriber {
+
+  protected function isErrorDisplayable($error) {
+    return TRUE;
+  }
+
+  protected function simplifyFileInError($error) {
+    return $error;
+  }
+
+  protected function isErrorLevelVerbose() {
+    return TRUE;
+  }
+
+}
\ No newline at end of file
