 .../CacheableAccessDeniedHttpException.php         | 23 ++++++++++++++++++++++
 .../Exception/CacheableBadRequestHttpException.php | 22 +++++++++++++++++++++
 .../Exception/CacheableConflictHttpException.php   | 22 +++++++++++++++++++++
 .../Cache/Exception/CacheableGoneHttpException.php | 22 +++++++++++++++++++++
 .../Cache/Exception/CacheableHttpException.php     | 22 +++++++++++++++++++++
 .../Exception/CacheableHttpExceptionInterface.php  | 12 +++++++++++
 .../CacheableLengthRequiredHttpException.php       | 23 ++++++++++++++++++++++
 .../CacheableMethodNotAllowedHttpException.php     | 23 ++++++++++++++++++++++
 .../CacheableNotAcceptableHttpException.php        | 23 ++++++++++++++++++++++
 .../Exception/CacheableNotFoundHttpException.php   | 23 ++++++++++++++++++++++
 .../CacheablePreconditionFailedHttpException.php   | 23 ++++++++++++++++++++++
 .../CacheablePreconditionRequiredHttpException.php | 23 ++++++++++++++++++++++
 .../CacheableServiceUnavailableHttpException.php   | 23 ++++++++++++++++++++++
 .../CacheableTooManyRequestsHttpException.php      | 23 ++++++++++++++++++++++
 .../CacheableUnauthorizedHttpException.php         | 23 ++++++++++++++++++++++
 .../CacheableUnprocessableEntityHttpException.php  | 23 ++++++++++++++++++++++
 .../CacheableUnsupportedMediaTypeHttpException.php | 23 ++++++++++++++++++++++
 core/lib/Drupal/Core/Entity/Entity.php             |  6 ++----
 .../DefaultExceptionHtmlSubscriber.php             |  7 +++++++
 .../EventSubscriber/DefaultExceptionSubscriber.php | 12 ++++++++++-
 .../EventSubscriber/ExceptionJsonSubscriber.php    | 11 ++++++++++-
 .../Routing/Enhancer/ParamConversionEnhancer.php   |  4 ++--
 .../src/Authentication/Provider/BasicAuth.php      | 10 ++++++++++
 .../src/Plugin/rest/resource/EntityResource.php    |  6 +++++-
 .../EventSubscriber/DefaultExceptionSubscriber.php | 15 ++++++++++++--
 .../Drupal/Tests/Core/Entity/EntityUnitTest.php    |  2 ++
 26 files changed, 438 insertions(+), 11 deletions(-)

diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableAccessDeniedHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableAccessDeniedHttpException.php
new file mode 100644
index 0000000..49750ec
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableAccessDeniedHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+
+/**
+ * An Access Denied
+ * exception that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableAccessDeniedHttpException extends AccessDeniedHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableBadRequestHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableBadRequestHttpException.php
new file mode 100644
index 0000000..d6ead4d
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableBadRequestHttpException.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
+
+/**
+ * A Bad Request exception that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableBadRequestHttpException extends BadRequestHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableConflictHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableConflictHttpException.php
new file mode 100644
index 0000000..69b638b
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableConflictHttpException.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
+
+/**
+ * A Conflict exception that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableConflictHttpException extends ConflictHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableGoneHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableGoneHttpException.php
new file mode 100644
index 0000000..f9c0c51
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableGoneHttpException.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\GoneHttpException;
+
+/**
+ * A Gone exception that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableGoneHttpException extends GoneHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableHttpException.php
new file mode 100644
index 0000000..599d7c1
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableHttpException.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+/**
+ * An exception that contains and can expose cacheability metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableHttpException extends HttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableHttpExceptionInterface.php b/core/lib/Drupal/Core/Cache/Exception/CacheableHttpExceptionInterface.php
new file mode 100644
index 0000000..44dfe4b
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableHttpExceptionInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseInterface;
+
+/**
+ * Defines an interface for exception that can expose cacheability metadata.
+ *
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+interface CacheableHttpExceptionInterface extends CacheableResponseInterface {}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableLengthRequiredHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableLengthRequiredHttpException.php
new file mode 100644
index 0000000..11bc935
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableLengthRequiredHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
+
+/**
+ * A Length Required exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableLengthRequiredHttpException extends LengthRequiredHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableMethodNotAllowedHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableMethodNotAllowedHttpException.php
new file mode 100644
index 0000000..1b1d07b
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableMethodNotAllowedHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+
+/**
+ * A Method Not Allowed exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableMethodNotAllowedHttpException extends MethodNotAllowedHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableNotAcceptableHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableNotAcceptableHttpException.php
new file mode 100644
index 0000000..e12a070
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableNotAcceptableHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
+
+/**
+ * A Not Acceptable exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableNotAcceptableHttpException extends NotAcceptableHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableNotFoundHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableNotFoundHttpException.php
new file mode 100644
index 0000000..98688f2
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableNotFoundHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+/**
+ * A Not Found exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableNotFoundHttpException extends NotFoundHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionFailedHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionFailedHttpException.php
new file mode 100644
index 0000000..3a6d5c7
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionFailedHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
+
+/**
+ * A Precondition Failed exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheablePreconditionFailedHttpException extends PreconditionFailedHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionRequiredHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionRequiredHttpException.php
new file mode 100644
index 0000000..44955c8
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheablePreconditionRequiredHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
+
+/**
+ * A Precondition Required exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheablePreconditionRequiredHttpException extends PreconditionRequiredHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableServiceUnavailableHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableServiceUnavailableHttpException.php
new file mode 100644
index 0000000..f2b92a9
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableServiceUnavailableHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
+
+/**
+ * A Service Unavailable exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableServiceUnavailableHttpException extends ServiceUnavailableHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableTooManyRequestsHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableTooManyRequestsHttpException.php
new file mode 100644
index 0000000..d8620c9
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableTooManyRequestsHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
+
+/**
+ * A Too Many Requests exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableTooManyRequestsHttpException extends TooManyRequestsHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableUnauthorizedHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableUnauthorizedHttpException.php
new file mode 100644
index 0000000..ff250f5
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableUnauthorizedHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
+
+/**
+ * An Unauthorized exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableUnauthorizedHttpException extends UnauthorizedHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableUnprocessableEntityHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableUnprocessableEntityHttpException.php
new file mode 100644
index 0000000..140d333
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableUnprocessableEntityHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
+
+/**
+ * An Unprocessable Entity exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableUnprocessableEntityHttpException extends UnprocessableEntityHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Cache/Exception/CacheableUnsupportedMediaTypeHttpException.php b/core/lib/Drupal/Core/Cache/Exception/CacheableUnsupportedMediaTypeHttpException.php
new file mode 100644
index 0000000..dc9ffd1
--- /dev/null
+++ b/core/lib/Drupal/Core/Cache/Exception/CacheableUnsupportedMediaTypeHttpException.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Drupal\Core\Cache\Exception;
+
+use Drupal\Core\Cache\CacheableResponseTrait;
+use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
+
+/**
+ * An Unsupported Media Type exception that contains and can expose cacheability
+ * metadata.
+ *
+ * Supports Drupal's caching concepts: cache tags for invalidation and cache
+ * contexts for variations.
+ *
+ * @see \Drupal\Core\Cache\Cache
+ * @see \Drupal\Core\Cache\CacheableMetadata
+ * @see \Drupal\Core\Cache\CacheableResponseTrait
+ */
+class CacheableUnsupportedMediaTypeHttpException extends UnsupportedMediaTypeHttpException implements CacheableHttpExceptionInterface  {
+
+  use CacheableResponseTrait;
+
+}
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index f36f74f..6f28060 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -527,10 +527,8 @@ protected function invalidateTagsOnSave($update) {
     // listing's filtering requirements. A newly created entity may start to
     // appear in listings because it did not exist before.)
     $tags = $this->getEntityType()->getListCacheTags();
-    if ($this->hasLinkTemplate('canonical')) {
-      // Creating or updating an entity may change a cached 403 or 404 response.
-      $tags = Cache::mergeTags($tags, ['4xx-response']);
-    }
+    // Creating or updating an entity may change a cached 403 or 404 response.
+    $tags = Cache::mergeTags($tags, ['4xx-response']);
     if ($update) {
       // An existing entity was updated, also invalidate its unique cache tag.
       $tags = Cache::mergeTags($tags, $this->getCacheTagsToInvalidate());
diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
index 38cb895..76528d9 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Core\EventSubscriber;
 
+use Drupal\Core\Cache\CacheableResponseInterface;
+use Drupal\Core\Cache\Exception\CacheableHttpExceptionInterface;
 use Drupal\Core\Routing\RedirectDestinationInterface;
 use Drupal\Core\Utility\Error;
 use Psr\Log\LoggerInterface;
@@ -158,6 +160,11 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $url, $st
         $response->setStatusCode($status_code);
       }
 
+      // Persist any cacheability metadata.
+      if ($response instanceof CacheableResponseInterface && $exception instanceof CacheableHttpExceptionInterface) {
+        $response->addCacheableDependency($exception->getCacheableMetadata());
+      }
+
       // Persist any special HTTP headers that were set on the exception.
       if ($exception instanceof HttpExceptionInterface) {
         $response->headers->add($exception->getHeaders());
diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
index 7b5ecc1..361e4e8 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionSubscriber.php
@@ -3,6 +3,8 @@
 namespace Drupal\Core\EventSubscriber;
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Cache\CacheableResponse;
+use Drupal\Core\Cache\Exception\CacheableHttpExceptionInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Utility\Error;
@@ -118,7 +120,15 @@ protected function onHtml(GetResponseForExceptionEvent $event) {
 
     $content = $this->t('The website encountered an unexpected error. Please try again later.');
     $content .= $message ? '</br></br>' . $message : '';
-    $response = new Response($content, 500, ['Content-Type' => 'text/plain']);
+
+    // Persist any cacheability metadata.
+    if ($exception instanceof CacheableHttpExceptionInterface) {
+      $response = new CacheableResponse($content, 500, ['Content-Type' => 'text/plain']);
+      $response->addCacheableDependency($exception->getCacheableMetadata());
+    }
+    else {
+      $response = new Response($content, 500, ['Content-Type' => 'text/plain']);
+    }
 
     if ($exception instanceof HttpExceptionInterface) {
       $response->setStatusCode($exception->getStatusCode());
diff --git a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
index 6ccb743..4aa43ba 100644
--- a/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/ExceptionJsonSubscriber.php
@@ -35,7 +35,16 @@ protected static function getPriority() {
   public function on4xx(GetResponseForExceptionEvent $event) {
     /** @var \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface $exception */
     $exception = $event->getException();
-    $response = new JsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode(), $exception->getHeaders());
+
+    // Persist any cacheability metadata.
+    if ($exception instanceof CacheableHttpExceptionInterface) {
+      $response = new CacheableJsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode(), $exception->getHeaders());
+      $response->addCacheableDependency($exception->getCacheableMetadata());
+    }
+    else {
+      $response = new JsonResponse(['message' => $event->getException()->getMessage()], $exception->getStatusCode(), $exception->getHeaders());
+    }
+
     $event->setResponse($response);
   }
 
diff --git a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
index 09d6148..b1a2026 100644
--- a/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
+++ b/core/lib/Drupal/Core/Routing/Enhancer/ParamConversionEnhancer.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Core\Routing\Enhancer;
 
+use Drupal\Core\Cache\Exception\CacheableNotFoundHttpException;
 use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
 use Drupal\Core\ParamConverter\ParamNotConvertedException;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@@ -9,7 +10,6 @@
 use Symfony\Component\HttpFoundation\ParameterBag;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
-use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpKernel\KernelEvents;
 use Symfony\Component\Routing\Route;
 
@@ -77,7 +77,7 @@ protected function copyRawVariables(array $defaults) {
   public function onException(GetResponseForExceptionEvent $event) {
     $exception = $event->getException();
     if ($exception instanceof ParamNotConvertedException) {
-      $event->setException(new NotFoundHttpException($exception->getMessage(), $exception));
+      $event->setException(new CacheableNotFoundHttpException($exception->getMessage(), $exception));
     }
   }
 
diff --git a/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php b/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
index c72e3f0..a1263ee 100644
--- a/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
+++ b/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
@@ -5,6 +5,8 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Authentication\AuthenticationProviderInterface;
 use Drupal\Core\Authentication\AuthenticationProviderChallengeInterface;
+use Drupal\Core\Cache\Exception\CacheableHttpExceptionInterface;
+use Drupal\Core\Cache\Exception\CacheableUnauthorizedHttpException;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Flood\FloodInterface;
@@ -130,6 +132,14 @@ public function challengeException(Request $request, \Exception $previous) {
     $challenge = SafeMarkup::format('Basic realm="@realm"', [
       '@realm' => !empty($site_name) ? $site_name : 'Access restricted',
     ]);
+
+    // Persist any cacheability metadata.
+    if ($previous instanceof CacheableHttpExceptionInterface) {
+      $exception = new CacheableUnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous);
+      $exception->addCacheableDependency($previous->getCacheableMetadata());
+      return $exception;
+    }
+
     return new UnauthorizedHttpException((string) $challenge, 'No authentication credentials provided.', $previous);
   }
 
diff --git a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
index 9b1d15f..73f2ca2 100644
--- a/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/src/Plugin/rest/resource/EntityResource.php
@@ -5,6 +5,7 @@
 use Drupal\Component\Plugin\DependentPluginInterface;
 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\Cache\CacheableResponseInterface;
+use Drupal\Core\Cache\Exception\CacheableAccessDeniedHttpException;
 use Drupal\Core\Config\Entity\ConfigEntityType;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\Entity\FieldableEntityInterface;
@@ -122,7 +123,10 @@ public static function create(ContainerInterface $container, array $configuratio
   public function get(EntityInterface $entity) {
     $entity_access = $entity->access('view', NULL, TRUE);
     if (!$entity_access->isAllowed()) {
-      throw new AccessDeniedHttpException($entity_access->getReason() ?: $this->generateFallbackAccessDeniedMessage($entity, 'view'));
+      $exception = new CacheableAccessDeniedHttpException($entity_access->getReason() ?: $this->generateFallbackAccessDeniedMessage($entity, 'view'));
+      $exception->addCacheableDependency($entity);
+      $exception->addCacheableDependency($entity_access);
+      throw $exception;
     }
 
     $response = new ResourceResponse($entity, 200);
diff --git a/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php b/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php
index a1e7bad..2afe643 100644
--- a/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php
+++ b/core/modules/serialization/src/EventSubscriber/DefaultExceptionSubscriber.php
@@ -2,9 +2,12 @@
 
 namespace Drupal\serialization\EventSubscriber;
 
+use Drupal\Core\Cache\CacheableResponse;
+use Drupal\Core\Cache\Exception\CacheableHttpExceptionInterface;
 use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
 use Symfony\Component\Serializer\SerializerInterface;
 
 /**
@@ -67,14 +70,22 @@ public function on4xx(GetResponseForExceptionEvent $event) {
     $request = $event->getRequest();
 
     $format = $request->getRequestFormat();
-    $content = ['message' => $event->getException()->getMessage()];
+    $content = ['message' => $exception->getMessage()];
     $encoded_content = $this->serializer->serialize($content, $format);
     $headers = $exception->getHeaders();
 
     // Add the MIME type from the request to send back in the header.
     $headers['Content-Type'] = $request->getMimeType($format);
 
-    $response = new Response($encoded_content, $exception->getStatusCode(), $headers);
+    // Persist any cacheability metadata.
+    if ($exception instanceof CacheableHttpExceptionInterface) {
+      $response = new CacheableResponse($encoded_content, $exception->getStatusCode(), $headers);
+      $response->addCacheableDependency($exception->getCacheableMetadata());
+    }
+    else {
+      $response = new Response($encoded_content, $exception->getStatusCode(), $headers);
+    }
+
     $event->setResponse($response);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
index ad9e49c..285d249 100644
--- a/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php
@@ -392,11 +392,13 @@ public function testPostSave() {
     $this->cacheTagsInvalidator->expects($this->at(0))
       ->method('invalidateTags')
       ->with([
+        '4xx-response',
         $this->entityTypeId . '_list', // List cache tag.
       ]);
     $this->cacheTagsInvalidator->expects($this->at(1))
       ->method('invalidateTags')
       ->with([
+        '4xx-response',
         $this->entityTypeId . ':' . $this->values['id'], // Own cache tag.
         $this->entityTypeId . '_list', // List cache tag.
       ]);
