diff --git a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
index 2853b98..41100cf 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
@@ -3,7 +3,6 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
 
 /**
@@ -39,46 +38,15 @@ public function on400(GetResponseForExceptionEvent $event) {
   }
 
   /**
-   * Handles a 403 error for JSON.
+   * Handles all 4xx errors for JSON.
    *
    * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
    *   The event to process.
    */
-  public function on403(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_FORBIDDEN);
-    $event->setResponse($response);
-  }
-
-  /**
-   * Handles a 404 error for JSON.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
-   *   The event to process.
-   */
-  public function on404(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_NOT_FOUND);
-    $event->setResponse($response);
-  }
-
-  /**
-   * Handles a 405 error for JSON.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
-   *   The event to process.
-   */
-  public function on405(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(array('message' => $event->getException()->getMessage()), Response::HTTP_METHOD_NOT_ALLOWED);
-    $event->setResponse($response);
-  }
-
-  /**
-   * Handles a 406 error for JSON.
-   *
-   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
-   *   The event to process.
-   */
-  public function on406(GetResponseForExceptionEvent $event) {
-    $response = new JsonResponse(['message' => $event->getException()->getMessage()], Response::HTTP_NOT_ACCEPTABLE);
+  public function on4xx(GetResponseForExceptionEvent $event) {
+    /** @var \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $exception */
+    $exception = $event->getException();
+    $response = new JsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode());
     $event->setResponse($response);
   }
 
diff --git a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
index 90ff028..d1029ef 100644
--- a/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
+++ b/core/lib/Drupal/Core/EventSubscriber/HttpExceptionSubscriberBase.php
@@ -13,12 +13,20 @@
  * A subscriber may extend this class and implement getHandledFormats() to
  * indicate which request formats it will respond to. Then implement an on*()
  * method for any error code (HTTP response code) that should be handled. For
- * example, to handle 404 Not Found messages add a method:
+ * example, to handle a specific error code like 404 Not Found messages add the
+ * method:
  *
  * @code
  * public function on404(GetResponseForExceptionEvent $event) {}
  * @endcode
  *
+ * To implement a fallback for the entire 4XX class of codes, implement the
+ * method:
+ *
+ * @code
+ * public function on4XX(GetResponseForExceptionEvent $event) {}
+ * @endcode
+ *
  * That method should then call $event->setResponse() to set the response object
  * for the exception. Alternatively, it may opt not to do so and then other
  * listeners will have the opportunity to handle the exception.
@@ -90,6 +98,9 @@ public function onException(GetResponseForExceptionEvent $event) {
 
     if ($exception instanceof HttpExceptionInterface && (empty($handled_formats) || in_array($format, $handled_formats))) {
       $method = 'on' . $exception->getStatusCode();
+      // Keep just the leading number of the status code to produce either a
+      // on400 or a 500 method callback.
+      $method_fallback = 'on' . floor($exception->getStatusCode() / 100) . 'xx';
       // We want to allow the method to be called and still not set a response
       // if it has additional filtering logic to determine when it will apply.
       // It is therefore the method's responsibility to set the response on the
@@ -97,6 +108,9 @@ public function onException(GetResponseForExceptionEvent $event) {
       if (method_exists($this, $method)) {
         $this->$method($event);
       }
+      elseif (method_exists($this, $method_fallback)) {
+        $this->$method_fallback($event);
+      }
     }
   }
 
diff --git a/core/modules/rest/src/Tests/AuthTest.php b/core/modules/rest/src/Tests/AuthTest.php
index 9f4224f..1e570ac 100644
--- a/core/modules/rest/src/Tests/AuthTest.php
+++ b/core/modules/rest/src/Tests/AuthTest.php
@@ -34,7 +34,7 @@ public function testRead() {
     // Try to read the resource as an anonymous user, which should not work.
     $this->httpRequest($entity->urlInfo()->setRouteParameter('_format', $this->defaultFormat), 'GET');
     $this->assertResponse('401', 'HTTP response code is 401 when the request is not authenticated and the user is anonymous.');
-    $this->assertRaw(json_encode(['message' => 'A fatal error occurred: No authentication credentials provided.']));
+    $this->assertRaw(json_encode(['message' => 'No authentication credentials provided.']));
 
     // Ensure that cURL settings/headers aren't carried over to next request.
     unset($this->curlHandle);
