Index: wp-includes/class-simplepie.php
===================================================================
--- wp-includes/class-simplepie.php	(revision 24806)
+++ wp-includes/class-simplepie.php	(working copy)
@@ -557,6 +557,13 @@
 	public $cache_duration = 3600;
 
 	/**
+	 * @var int Error cache duration (in seconds)
+	 * @see SimplePie::set_error_cache_duration()
+	 * @access private
+	 */
+	public $error_cache_duration = 3600;
+
+	/**
 	 * @var int Auto-discovery cache duration (in seconds)
 	 * @see SimplePie::set_autodiscovery_cache_duration()
 	 * @access private
@@ -877,6 +884,17 @@
 	}
 
 	/**
+	 * Set the length of time (in seconds) that the errors for failed feed loads
+	 * will be cached
+	 *
+	 * @param int $seconds The feed error cache duration
+	 */
+	public function set_error_cache_duration($seconds = 3600)
+	{
+		$this->error_cache_duration = (int) $seconds;
+	}
+
+	/**
 	 * Set the length of time (in seconds) that the autodiscovered feed URL will
 	 * be cached
 	 *
@@ -1470,12 +1488,14 @@
 					$cache->unlink();
 					$this->data = array();
 				}
+
 				// If we've hit a collision just rerun it with caching disabled
 				elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
 				{
 					$cache = false;
 					$this->data = array();
 				}
+
 				// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
 				elseif (isset($this->data['feed_url']))
 				{
@@ -1493,6 +1513,14 @@
 						$this->data = array();
 					}
 				}
+
+				// Check if the error cache has been updated
+				elseif ($cache->mtime() + $this->error_cache_duration < time() && isset($this->data['error']))
+				{
+					$cache->unlink();
+					$this->data = array();
+				}
+
 				// Check if the cache has been updated
 				elseif ($cache->mtime() + $this->cache_duration < time())
 				{
@@ -1527,13 +1555,20 @@
 						}
 					}
 				}
+
 				// If the cache is still valid, just return true
 				else
 				{
+					// If we're caching an error, pull it back out from the cache payload for persistent error response.
+					if (!empty($this->data['error']))
+					{
+						$this->error = $this->data['error'];
+					}
 					$this->raw_data = false;
 					return true;
 				}
 			}
+
 			// If the cache is empty, delete it
 			else
 			{
@@ -1541,6 +1576,7 @@
 				$this->data = array();
 			}
 		}
+
 		// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
 		if (!isset($file))
 		{
@@ -1553,6 +1589,7 @@
 				$headers = array(
 					'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
 				);
+
 				$file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
 			}
 		}
@@ -1560,6 +1597,7 @@
 		if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
 		{
 			$this->error = $file->error;
+			$this->cache_results( $cache, $this->feed_url );
 			return !empty($this->data);
 		}
 
@@ -1578,6 +1616,7 @@
 					{
 						$this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
 						$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
+						$this->cache_results( $cache, $this->feed_url );
 						return false;
 					}
 				}
@@ -1586,17 +1625,11 @@
 					// This is usually because DOMDocument doesn't exist
 					$this->error = $e->getMessage();
 					$this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
+					$this->cache_results( $cache, $this->feed_url );
 					return false;
 				}
-				if ($cache)
-				{
-					$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
-					if (!$cache->save($this))
-					{
-						trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-					}
-					$cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
-				}
+
+				$this->cache_results( $cache, $file->url );
 				$this->feed_url = $file->url;
 			}
 			$locate = null;
@@ -1611,7 +1644,39 @@
 		return array($headers, $sniffed);
 	}
 
+
 	/**
+	 * Cache the results of the feed request.
+	 *
+	 * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
+	 * @param string $feedurl
+	 */
+	public function cache_results( &$cache, $feedurl )
+	{
+		if ($cache)
+		{
+			$this->data = array('url' => $this->feed_url, 'build' => SIMPLEPIE_BUILD);
+
+			// A weird little hack to ensure that we cache errors.
+			if (!empty($this->error))
+			{
+				$this->data['error'] = $this->error;
+			}
+			// For some reason feed_url in the cache payload should only be set if there are no errors.
+			else {
+				$this->data['feed_url'] = $feedurl;
+			}
+
+			if (!$cache->save($this))
+			{
+				trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
+			}
+
+			$this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $feedurl), 'spc'));
+		}
+	}
+
+	/**
 	 * Get the error message for the occured error
 	 *
 	 * @return string|array Error message, or array of messages for multifeeds
Index: wp-includes/default-widgets.php
===================================================================
--- wp-includes/default-widgets.php	(revision 24806)
+++ wp-includes/default-widgets.php	(working copy)
@@ -833,7 +833,7 @@
 
 	if ( is_wp_error($rss) ) {
 		if ( is_admin() || current_user_can('manage_options') )
-			echo '<p>' . sprintf( __('<strong>RSS Error</strong>: %s'), $rss->get_error_message() ) . '</p>';
+			echo '<p class="error">' . sprintf( __('<strong>RSS Error</strong>: %s'), $rss->get_error_message() ) . '</p>';
 		return;
 	}
 
Index: wp-includes/feed.php
===================================================================
--- wp-includes/feed.php	(revision 24806)
+++ wp-includes/feed.php	(working copy)
@@ -541,6 +541,7 @@
 
 	$feed->set_feed_url( $url );
 	$feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) );
+	$feed->set_error_cache_duration( apply_filters( 'wp_feed_error_cache_transient_lifetime', 15 * MINUTE_IN_SECONDS, $url ) );
 	do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) );
 	$feed->init();
 	$feed->handle_content_type();
