diff --git a/src/aphront/configuration/AphrontApplicationConfiguration.php b/src/aphront/configuration/AphrontApplicationConfiguration.php
--- a/src/aphront/configuration/AphrontApplicationConfiguration.php
+++ b/src/aphront/configuration/AphrontApplicationConfiguration.php
@@ -312,11 +312,17 @@
     if ($response_exception) {
       // If we encountered an exception while building a normal response, then
       // encountered another exception while building a response for the first
-      // exception, just throw the original exception. It is more likely to be
-      // useful and point at a root cause than the second exception we ran into
-      // while telling the user about it.
+      // exception, throw an aggregate exception that will be unpacked by the
+      // higher-level handler. This is above our pay grade.
       if ($original_exception) {
-        throw $original_exception;
+        throw new PhutilAggregateException(
+          pht(
+            'Encountered a processing exception, then another exception when '.
+            'trying to build a response for the first exception.'),
+          array(
+            $response_exception,
+            $original_exception,
+          ));
       }
 
       // If we built a response successfully and then ran into an exception
diff --git a/src/aphront/response/AphrontUnhandledExceptionResponse.php b/src/aphront/response/AphrontUnhandledExceptionResponse.php
--- a/src/aphront/response/AphrontUnhandledExceptionResponse.php
+++ b/src/aphront/response/AphrontUnhandledExceptionResponse.php
@@ -61,9 +61,39 @@
     return 'unhandled-exception';
   }
 
+  private function getExceptionList() {
+    return $this->expandException($this->exception);
+  }
+
+  private function expandException($root) {
+    if ($root instanceof PhutilAggregateException) {
+      $list = array();
+
+      $list[] = $root;
+
+      foreach ($root->getExceptions() as $ex) {
+        foreach ($this->expandException($ex) as $child) {
+          $list[] = $child;
+        }
+      }
+
+      return $list;
+    }
+
+    return array($root);
+  }
+
   protected function getResponseBody() {
-    $ex = $this->exception;
+    $body = array();
+
+    foreach ($this->getExceptionList() as $ex) {
+      $body[] = $this->newHTMLMessage($ex);
+    }
+
+    return $body;
+  }
 
+  private function newHTMLMessage($ex) {
     if ($ex instanceof AphrontMalformedRequestException) {
       $title = $ex->getTitle();
     } else {
@@ -122,12 +152,20 @@
   }
 
   protected function buildPlainTextResponseString() {
-    $ex = $this->exception;
+    $messages = array();
+
+    foreach ($this->getExceptionList() as $exception) {
+      $messages[] = $this->newPlainTextMessage($exception);
+    }
+
+    return implode("\n\n", $messages);
+  }
 
+  private function newPlainTextMessage($exception) {
     return pht(
       '%s: %s',
-      get_class($ex),
-      $ex->getMessage());
+      get_class($exception),
+      $exception->getMessage());
   }
 
 }