diff --git a/core/API/Proxy.php b/core/API/Proxy.php
index 1576df9ba0723f951a2b0dc7800fc98505076747..26e2ceb4cca9d2b3542ff7f5346daa7137256979 100644
--- a/core/API/Proxy.php
+++ b/core/API/Proxy.php
@@ -37,10 +37,7 @@ class Proxy extends Singleton
     // when a parameter doesn't have a default value we use this
     private $noDefaultValue;
 
-    /**
-     * protected constructor
-     */
-    protected function __construct()
+    public function __construct()
     {
         $this->noDefaultValue = new NoDefaultValue();
     }
diff --git a/core/ReportRenderer.php b/core/ReportRenderer.php
index 6b809f5b1697a893ee114f1225b1d6f7ed427040..3fa20aff43f36836d496f3463edc664e324800ca 100644
--- a/core/ReportRenderer.php
+++ b/core/ReportRenderer.php
@@ -177,17 +177,17 @@ abstract class ReportRenderer extends BaseFactory
         $filename = ReportRenderer::makeFilenameWithExtension($filename, $extension);
 
         ProxyHttp::overrideCacheControlHeaders();
-        header('Content-Description: File Transfer');
-        header('Content-Type: ' . $contentType);
-        header('Content-Disposition: attachment; filename="' . str_replace('"', '\'', basename($filename)) . '";');
-        header('Content-Length: ' . strlen($content));
+        Common::sendHeader('Content-Description: File Transfer');
+        Common::sendHeader('Content-Type: ' . $contentType);
+        Common::sendHeader('Content-Disposition: attachment; filename="' . str_replace('"', '\'', basename($filename)) . '";');
+        Common::sendHeader('Content-Length: ' . strlen($content));
 
         echo $content;
     }
 
     protected static function inlineToBrowser($contentType, $content)
     {
-        header('Content-Type: ' . $contentType);
+        Common::sendHeader('Content-Type: ' . $contentType);
         echo $content;
     }
 
diff --git a/core/Singleton.php b/core/Singleton.php
index 499fb28e52609d73cc23e0621d5d7b118bdc77c8..cde63cb744916a4eb560c3d1b24ab4587614ff8c 100644
--- a/core/Singleton.php
+++ b/core/Singleton.php
@@ -63,4 +63,12 @@ class Singleton
         $class = get_called_class();
         self::$instances[$class] = $instance;
     }
+
+    /**
+     * @ignore
+     */
+    public static function clearAll()
+    {
+        self::$instances = array();
+    }
 }
diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php
index 6e31a13317320e5b9ee1f2c6ec809732dab75b12..c7086080896ef4260e6ba1a3b6fcd301b378eaff 100644
--- a/plugins/API/RowEvolution.php
+++ b/plugins/API/RowEvolution.php
@@ -360,9 +360,16 @@ class RowEvolution
         unset($metadata['logos']);
 
         $subDataTables = $dataTable->getDataTables();
+        if (empty($subDataTables)) {
+            throw new \Exception("Unexpected state: row evolution API call returned empty DataTable\\Map.");
+        }
+
         $firstDataTable = reset($subDataTables);
+        $this->checkDataTableInstance($firstDataTable);
         $firstDataTableRow = $firstDataTable->getFirstRow();
+
         $lastDataTable = end($subDataTables);
+        $this->checkDataTableInstance($lastDataTable);
         $lastDataTableRow = $lastDataTable->getFirstRow();
 
         // Process min/max values
@@ -533,4 +540,11 @@ class RowEvolution
         $label = SafeDecodeLabel::decodeLabelSafe($label);
         return $label;
     }
+
+    private function checkDataTableInstance($lastDataTable)
+    {
+        if (!($lastDataTable instanceof DataTable)) {
+            throw new \Exception("Unexpected state: row evolution returned DataTable\\Map w/ incorrect child table type: " . get_class($lastDataTable));
+        }
+    }
 }
diff --git a/plugins/ScheduledReports/API.php b/plugins/ScheduledReports/API.php
index f77fa4b2237265f523d9d49ba322a4379b288929..d5a985e65b4322977e937446232bc770e2c11633 100644
--- a/plugins/ScheduledReports/API.php
+++ b/plugins/ScheduledReports/API.php
@@ -26,6 +26,9 @@ use Piwik\Site;
 use Piwik\Tracker;
 use Piwik\Translate;
 use Piwik\Translation\Translator;
+use Piwik\Url;
+use Piwik\UrlHelper;
+use Psr\Log\LoggerInterface;
 
 /**
  * The ScheduledReports API lets you manage Scheduled Email reports, as well as generate, download or email any existing report.
@@ -60,6 +63,16 @@ class API extends \Piwik\Plugin\API
     // static cache storing reports
     public static $cache = array();
 
+    /**
+     * @var LoggerInterface
+     */
+    private $logger;
+
+    public function __construct(LoggerInterface $logger)
+    {
+        $this->logger = $logger;
+    }
+
     /**
      * Creates a new report and schedules it.
      *
@@ -377,7 +390,20 @@ class API extends \Piwik\Plugin\API
                 $params['segment'] = false;
             }
 
-            $processedReport = Request::processRequest('API.getProcessedReport', $params);
+            try {
+                $processedReport = Request::processRequest('API.getProcessedReport', $params);
+            } catch (\Exception $ex) {
+                // NOTE: can't use warning or error because the log message will appear in the UI as a notification
+                $this->logger->info("Error getting '?{report}' when generating scheduled report: {exception}", array(
+                    'report' => http_build_query($params),
+                    'exception' => $ex->getMessage(),
+                ));
+
+                $this->logger->debug($ex);
+
+                continue;
+            }
+
             $processedReport['segment'] = $segment;
 
             // TODO add static method getPrettyDate($period, $date) in Period
diff --git a/plugins/ScheduledReports/tests/Integration/ApiTest.php b/plugins/ScheduledReports/tests/Integration/ApiTest.php
index 8ac7ac4c262534a2388f05de061580de215d11be..2f4b4020fa4ede6238749d43871bbd0b22391d4a 100644
--- a/plugins/ScheduledReports/tests/Integration/ApiTest.php
+++ b/plugins/ScheduledReports/tests/Integration/ApiTest.php
@@ -8,12 +8,18 @@
 
 namespace Piwik\Plugins\ScheduledReports\tests;
 
+use Piwik\API\Proxy;
+use Piwik\DataTable;
+use Piwik\Date;
+use Piwik\Plugins\API\API;
 use Piwik\Plugins\MobileMessaging\API as APIMobileMessaging;
 use Piwik\Plugins\MobileMessaging\MobileMessaging;
 use Piwik\Plugins\ScheduledReports\API as APIScheduledReports;
 use Piwik\Plugins\ScheduledReports\Menu;
+use Piwik\Plugins\ScheduledReports\ScheduledReports;
 use Piwik\Plugins\ScheduledReports\Tasks;
 use Piwik\Plugins\SitesManager\API as APISitesManager;
+use Piwik\ReportRenderer;
 use Piwik\Scheduler\Schedule\Monthly;
 use Piwik\Scheduler\Schedule\Schedule;
 use Piwik\Scheduler\Task;
@@ -41,7 +47,8 @@ class ApiTest extends IntegrationTestCase
 
         // setup the access layer
         self::setSuperUser();
-        \Piwik\Plugin\Manager::getInstance()->loadPlugins(array('API', 'UserCountry', 'ScheduledReports', 'MobileMessaging'));
+        \Piwik\Plugin\Manager::getInstance()->loadPlugins(array('API', 'UserCountry', 'ScheduledReports',
+            'MobileMessaging', 'VisitsSummary', 'Referrers'));
         \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins();
 
         APISitesManager::getInstance()->addSite("Test", array("http://piwik.net"));
@@ -426,6 +433,56 @@ class ApiTest extends IntegrationTestCase
         $this->assertEquals($expectedReportTitle, $reportTitle);
     }
 
+    public function test_generateReport_CatchesIndividualReportProcessExceptions_WithoutFailingToGenerateWholeReport()
+    {
+        $realProxy = new Proxy();
+
+        $mockProxy = $this->getMock('Piwik\API\Proxy', array('call'));
+        $mockProxy->expects($this->any())->method('call')->willReturnCallback(function ($className, $methodName, $parametersRequest) use ($realProxy) {
+            switch ($className) {
+                case '\Piwik\Plugins\VisitsSummary\API':
+                    $result = new DataTable();
+                    $result->addRowFromSimpleArray(array('label' => 'visits label', 'nb_visits' => 1));
+                    return $result;
+                case '\Piwik\Plugins\UserCountry\API':
+                    throw new \Exception("error");
+                case '\Piwik\Plugins\Referrers\API':
+                    $result = new DataTable();
+                    $result->addRowFromSimpleArray(array('label' => 'referrers label', 'nb_visits' => 1));
+                    return $result;
+                case '\Piwik\Plugins\API\API':
+                    return $realProxy->call($className, $methodName, $parametersRequest);
+                default:
+                    throw new \Exception("Unexpected method $className::$methodName.");
+            }
+        });
+        Proxy::setSingletonInstance($mockProxy);
+
+        $idReport = APIScheduledReports::getInstance()->addReport(
+            1,
+            '',
+            Schedule::PERIOD_DAY,
+            0,
+            ScheduledReports::EMAIL_TYPE,
+            ReportRenderer::HTML_FORMAT,
+            array(
+                'VisitsSummary_get',
+                'UserCountry_getCountry',
+                'Referrers_getWebsites',
+            ),
+            array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
+        );
+
+        ob_start();
+        $result = APIScheduledReports::getInstance()->generateReport($idReport, Date::factory('now')->toString(),
+            $language = false, $outputType = APIScheduledReports::OUTPUT_RETURN);
+        ob_end_clean();
+
+        $this->assertContains('id="VisitsSummary_get"', $result);
+        $this->assertContains('id="Referrers_getWebsites"', $result);
+        $this->assertNotContains('id="UserCountry_getCountry"', $result);
+    }
+
     private function assertReportsEqual($report, $data)
     {
         foreach ($data as $key => $value) {
diff --git a/tests/PHPUnit/Framework/Fixture.php b/tests/PHPUnit/Framework/Fixture.php
index a048dad5167d469a299585d7af6585b60231edac..3d53b796d82e5c0aa31fb8098a512cf216736cb5 100644
--- a/tests/PHPUnit/Framework/Fixture.php
+++ b/tests/PHPUnit/Framework/Fixture.php
@@ -40,6 +40,7 @@ use Piwik\Plugins\UsersManager\UsersManager;
 use Piwik\ReportRenderer;
 use Piwik\SettingsPiwik;
 use Piwik\SettingsServer;
+use Piwik\Singleton;
 use Piwik\Site;
 use Piwik\Tests\Framework\Mock\FakeAccess;
 use Piwik\Tests\Framework\TestCase\SystemTestCase;
@@ -350,6 +351,7 @@ class Fixture extends \PHPUnit_Framework_Assert
         PiwikCache::getEagerCache()->flushAll();
         ArchiveTableCreator::clear();
         \Piwik\Plugins\ScheduledReports\API::$cache = array();
+        Singleton::clearAll();
 
         $_GET = $_REQUEST = array();
         Translate::reset();