diff --git a/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc b/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
index 587598a..bb91c17 100644
--- a/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
+++ b/contrib/search_api_facetapi/plugins/facetapi/query_type_term.inc
@@ -30,7 +30,7 @@ class SearchApiFacetapiTerm extends FacetapiQueryType implements FacetapiQueryTy
     // Return terms for this facet.
     $this->adapter->addFacet($this->facet, $query);
 
-    $settings = $this->adapter->getFacet($this->facet)->getSettings()->settings;
+    $settings = $this->getSettings()->settings;
 
     // First check if the facet is enabled for this search.
     $default_true = isset($settings['default_true']) ? $settings['default_true'] : TRUE;
@@ -56,7 +56,12 @@ class SearchApiFacetapiTerm extends FacetapiQueryType implements FacetapiQueryTy
       $conjunction = 'OR';
     }
     else {
-      throw new SearchApiException(t('Unknown facet operator %operator.', array('%operator' => $operator)));
+      $vars = array(
+        '%operator' => $operator,
+        '%facet' => !empty($this->facet['label']) ? $this->facet['label'] : $this->facet['name'],
+      );
+      watchdog('search_api_facetapi', 'Unknown facet operator %operator used for facet %facet.', $vars, WATCHDOG_WARNING);
+      return;
     }
     $tags = array('facet:' . $this->facet['field']);
     $facet_filter = $query->createFilter($conjunction, $tags);
@@ -77,7 +82,7 @@ class SearchApiFacetapiTerm extends FacetapiQueryType implements FacetapiQueryTy
     // Test if this filter should be negated.
     $settings = $this->adapter->getFacet($this->facet)->getSettings();
     $exclude = !empty($settings->settings['exclude']);
-    // Integer (or other nun-string) filters might mess up some of the following
+    // Integer (or other non-string) filters might mess up some of the following
     // comparison expressions.
     $filter = (string) $filter;
     if ($filter == '!') {
diff --git a/contrib/search_api_facetapi/search_api_facetapi.module b/contrib/search_api_facetapi/search_api_facetapi.module
index 29a2dbd..0e3da91 100644
--- a/contrib/search_api_facetapi/search_api_facetapi.module
+++ b/contrib/search_api_facetapi/search_api_facetapi.module
@@ -53,7 +53,7 @@ function search_api_facetapi_facetapi_searcher_info() {
   $info = array();
   $indexes = search_api_index_load_multiple(FALSE);
   foreach ($indexes as $index) {
-    if ($index->enabled && $index->server()->supportsFeature('search_api_facets')) {
+    if (_search_api_facetapi_index_support_feature($index)) {
       $searcher_name = 'search_api@' . $index->machine_name;
       $info[$searcher_name] = array(
         'label' => t('Search service: @name', array('@name' => $index->name)),
@@ -116,7 +116,7 @@ function search_api_facetapi_facetapi_facet_info(array $searcher_info) {
           'description' => t('Filter by @type.', array('@type' => $field['name'])),
           'allowed operators' => array(
             FACETAPI_OPERATOR_AND => TRUE,
-            FACETAPI_OPERATOR_OR => $index->server()->supportsFeature('search_api_facets_operator_or'),
+            FACETAPI_OPERATOR_OR => _search_api_facetapi_index_support_feature($index, 'search_api_facets_operator_or'),
           ),
           'dependency plugins' => array('role'),
           'facet missing allowed' => TRUE,
@@ -218,7 +218,7 @@ function search_api_facetapi_settings($realm_name, SearchApiIndex $index) {
   if (!$index->enabled) {
     return array('#markup' => t('Since this index is at the moment disabled, no facets can be activated.'));
   }
-  if (!$index->server()->supportsFeature('search_api_facets')) {
+  if (!_search_api_facetapi_index_support_feature($index)) {
     return array('#markup' => t('This index uses a server that does not support facet functionality.'));
   }
   $searcher_name = 'search_api@' . $index->machine_name;
@@ -227,6 +227,28 @@ function search_api_facetapi_settings($realm_name, SearchApiIndex $index) {
 }
 
 /**
+ * Checks whether a certain feature is supported for an index.
+ *
+ * @param SearchApiIndex $index
+ *   The search index which should be checked.
+ * @param string $feature
+ *   (optional) The feature to check for. Defaults to "search_api_facets".
+ *
+ * @return bool
+ *   TRUE if the feature is supported by the index's server (and the index is
+ *   currently enabled), FALSE otherwise.
+ */
+function _search_api_facetapi_index_support_feature(SearchApiIndex $index, $feature = 'search_api_facets') {
+  try {
+    $server = $index->server();
+    return $server && $server->supportsFeature($feature);
+  }
+  catch (SearchApiException $e) {
+    return FALSE;
+  }
+}
+
+/**
  * Gets hierarchy information for taxonomy terms.
  *
  * Used as a hierarchy callback in search_api_facetapi_facetapi_facet_info().
diff --git a/contrib/search_api_views/includes/handler_argument_more_like_this.inc b/contrib/search_api_views/includes/handler_argument_more_like_this.inc
index 9683c25..69e4a54 100644
--- a/contrib/search_api_views/includes/handler_argument_more_like_this.inc
+++ b/contrib/search_api_views/includes/handler_argument_more_like_this.inc
@@ -62,24 +62,30 @@ class SearchApiViewsHandlerArgumentMoreLikeThis extends SearchApiViewsHandlerArg
    * The argument sent may be found at $this->argument.
    */
   public function query($group_by = FALSE) {
-    $server = $this->query->getIndex()->server();
-    if (!$server->supportsFeature('search_api_mlt')) {
-      $class = search_api_get_service_info($server->class);
-      watchdog('search_api_views', 'The search service "@class" does not offer "More like this" functionality.',
+    try {
+      $server = $this->query->getIndex()->server();
+      if (!$server->supportsFeature('search_api_mlt')) {
+        $class = search_api_get_service_info($server->class);
+        watchdog('search_api_views', 'The search service "@class" does not offer "More like this" functionality.',
           array('@class' => $class['name']), WATCHDOG_ERROR);
-      $this->query->abort();
-      return;
-    }
-    $fields = $this->options['fields'] ? $this->options['fields'] : array();
-    if (empty($fields)) {
-      foreach ($this->query->getIndex()->options['fields'] as $key => $field) {
-        $fields[] = $key;
+        $this->query->abort();
+        return;
+      }
+      $fields = $this->options['fields'] ? $this->options['fields'] : array();
+      if (empty($fields)) {
+        foreach ($this->query->getIndex()->options['fields'] as $key => $field) {
+          $fields[] = $key;
+        }
       }
+      $mlt = array(
+        'id' => $this->argument,
+        'fields' => $fields,
+      );
+      $this->query->getSearchApiQuery()->setOption('search_api_mlt', $mlt);
+    }
+    catch (SearchApiException $e) {
+      $this->query->abort($e->getMessage());
     }
-    $mlt = array(
-      'id' => $this->argument,
-      'fields' => $fields,
-    );
-    $this->query->getSearchApiQuery()->setOption('search_api_mlt', $mlt);
   }
+
 }
diff --git a/includes/index_entity.inc b/includes/index_entity.inc
index b216884..10d5c90 100644
--- a/includes/index_entity.inc
+++ b/includes/index_entity.inc
@@ -180,12 +180,17 @@ class SearchApiIndex extends Entity {
    * Execute necessary tasks for a newly created index.
    */
   public function postCreate() {
-    if ($this->enabled) {
-      $this->queueItems();
+    try {
+      if ($server = $this->server()) {
+        // Tell the server about the new index.
+        $server->addIndex($this);
+        if ($this->enabled) {
+          $this->queueItems();
+        }
+      }
     }
-    if ($server = $this->server()) {
-      // Tell the server about the new index.
-      $server->addIndex($this);
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
     }
   }
 
@@ -193,8 +198,13 @@ class SearchApiIndex extends Entity {
    * Execute necessary tasks when the index is removed from the database.
    */
   public function postDelete() {
-    if ($server = $this->server()) {
-      $server->removeIndex($this);
+    try {
+      if ($server = $this->server()) {
+        $server->removeIndex($this);
+      }
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
     }
 
     // Stop tracking entities for indexing.
@@ -206,7 +216,12 @@ class SearchApiIndex extends Entity {
    */
   public function queueItems() {
     if (!$this->read_only) {
-      $this->datasource()->startTracking(array($this));
+      try {
+        $this->datasource()->startTracking(array($this));
+      }
+      catch (SearchApiException $e) {
+        watchdog_exception('search_api', $e);
+      }
     }
   }
 
@@ -214,7 +229,12 @@ class SearchApiIndex extends Entity {
    * Remove all records of entities to index.
    */
   public function dequeueItems() {
-    $this->datasource()->stopTracking(array($this));
+    try {
+      $this->datasource()->stopTracking(array($this));
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+    }
   }
 
   /**
@@ -231,15 +251,20 @@ class SearchApiIndex extends Entity {
     if (empty($this->description)) {
       $this->description = NULL;
     }
-    if (empty($this->server)) {
-      $this->server = NULL;
-      $this->enabled = FALSE;
+    $server = FALSE;
+    if (!empty($this->server)) {
+      $server = search_api_server_load($this->server);
+      if (!$server) {
+        $vars['%server'] = $this->server;
+        $vars['%index'] = $this->name;
+        watchdog('search_api', 'Unknown server %server specified for index %index.', $vars, WATCHDOG_ERROR);
+      }
     }
-    // This will also throw an exception if the server doesn't exist – which is good.
-    elseif (!$this->server(TRUE)->enabled) {
-      $this->enabled = FALSE;
+    if (!$server) {
       $this->server = NULL;
+      $this->enabled = FALSE;
     }
+    $this->resetCaches();
 
     return parent::save();
   }
@@ -305,7 +330,12 @@ class SearchApiIndex extends Entity {
       return TRUE;
     }
 
-    $this->server()->deleteItems('all', $this);
+    try {
+      $this->server()->deleteItems('all', $this);
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+    }
 
     _search_api_index_reindex($this);
     module_invoke_all('search_api_index_reindex', $this, TRUE);
@@ -350,7 +380,12 @@ class SearchApiIndex extends Entity {
    *   otherwise.
    */
   public function getEntityType() {
-    return $this->datasource()->getEntityType();
+    try {
+      return $this->datasource()->getEntityType();
+    }
+    catch (SearchApiException $e) {
+      return '';
+    }
   }
 
   /**
@@ -385,7 +420,7 @@ class SearchApiIndex extends Entity {
    *   SearchApiQueryInterface::__construct().
    *
    * @throws SearchApiException
-   *   If the index is currently disabled.
+   *   If the index is currently disabled or its server doesn't exist.
    *
    * @return SearchApiQueryInterface
    *   A query object for searching this index.
@@ -399,15 +434,20 @@ class SearchApiIndex extends Entity {
 
 
   /**
-   * Indexes items on this index. Will return an array of IDs of items that
-   * should be marked as indexed – i.e., items that were either rejected by a
-   * data-alter callback or were successfully indexed.
+   * Indexes items on this index.
+   *
+   * Will return an array of IDs of items that should be marked as indexed –
+   * i.e., items that were either rejected by a data-alter callback or were
+   * successfully indexed.
    *
    * @param array $items
-   *   An array of items to index.
+   *   An array of items to index, of this index's item type.
    *
    * @return array
    *   An array of the IDs of all items that should be marked as indexed.
+   *
+   * @throws SearchApiException
+   *   If an error occurred during indexing.
    */
   public function index(array $items) {
     if ($this->read_only) {
@@ -925,12 +965,18 @@ class SearchApiIndex extends Entity {
    * @return EntityMetadataWrapper
    *   A wrapper for the item type of this index, optionally loaded with the
    *   given data and having additional fields according to the data alterations
-   *   of this index.
+   *   of this index (if $alter wasn't set to FALSE).
    */
   public function entityWrapper($item = NULL, $alter = TRUE) {
-    $info['property info alter'] = $alter ? array($this, 'propertyInfoAlter') : '_search_api_wrapper_add_all_properties';
-    $info['property defaults']['property info alter'] = '_search_api_wrapper_add_all_properties';
-    return $this->datasource()->getMetadataWrapper($item, $info);
+    try {
+      $info['property info alter'] = $alter ? array($this, 'propertyInfoAlter') : '_search_api_wrapper_add_all_properties';
+      $info['property defaults']['property info alter'] = '_search_api_wrapper_add_all_properties';
+      return $this->datasource()->getMetadataWrapper($item, $info);
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+      return entity_metadata_wrapper($this->item_type);
+    }
   }
 
   /**
@@ -945,7 +991,13 @@ class SearchApiIndex extends Entity {
    * @see SearchApiDataSourceControllerInterface::loadItems()
    */
   public function loadItems(array $ids) {
-    return $this->datasource()->loadItems($ids);
+    try {
+      return $this->datasource()->loadItems($ids);
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+      return array();
+    }
   }
 
   /**
diff --git a/search_api.admin.inc b/search_api.admin.inc
index 51071b1..c1db495 100644
--- a/search_api.admin.inc
+++ b/search_api.admin.inc
@@ -831,6 +831,15 @@ function search_api_admin_index_view(SearchApiIndex $index, $action = NULL) {
   }
 
   $status = search_api_index_status($index);
+  try {
+    $server = $index->server();
+  }
+  catch (SearchApiException $e) {
+    $server = NULL;
+    $vars['%server'] = $index->server;
+    $message = t('The index has an unknown server (ID: %server) set. Please check the index settings.', $vars);
+    drupal_set_message($message, 'error');
+  }
   $ret['view'] = array(
     '#theme' => 'search_api_index',
     '#id' => $index->id,
@@ -839,7 +848,7 @@ function search_api_admin_index_view(SearchApiIndex $index, $action = NULL) {
     '#description' => $index->description,
     '#item_type' => $index->item_type,
     '#enabled' => $index->enabled,
-    '#server' => $index->server(),
+    '#server' => $server,
     '#options' => $index->options,
     '#fields' => $index->getFields(),
     '#indexed_items' => $status['indexed'],
@@ -1191,12 +1200,21 @@ function search_api_admin_index_edit(array $form, array &$form_state, SearchApiI
     '#default_value' => $index->name,
     '#required' => TRUE,
   );
+  try {
+    $enabled_fixed = !$index->enabled && !$index->server();
+  }
+  catch (Exception $e) {
+    watchdog_exception('search_api', $e);
+    // The exception only occurs if the index is disabled, and for an unknown
+    // server we of course want do prevent the index from being enabled.
+    $enabled_fixed = TRUE;
+  }
   $form['enabled'] = array(
     '#type' => 'checkbox',
     '#title' => t('Enabled'),
     '#default_value' => $index->enabled,
     // Can't enable an index lying on a disabled server, or no server at all.
-    '#disabled' => !$index->enabled && (!$index->server() || !$index->server()->enabled),
+    '#disabled' => $enabled_fixed,
   );
   $form['description'] = array(
     '#type' => 'textarea',
@@ -2222,8 +2240,16 @@ function search_api_admin_confirm_submit(array $form, array &$form_state) {
   $action = $values['action'];
   $id = $values['id'];
 
+  $success = FALSE;
   $function = "search_api_{$type}_{$action}";
-  if ($function($id)) {
+  try {
+    // Some actions, like disabling, can actually throw an exception.
+    $success = $function($id);
+  }
+  catch (SearchApiException $e) {
+    watchdog_exception('search_api', $e);
+  }
+  if ($success) {
     drupal_set_message($values['message']);
   }
   else {
diff --git a/search_api.drush.inc b/search_api.drush.inc
index 67e5f85..2322fb6 100644
--- a/search_api.drush.inc
+++ b/search_api.drush.inc
@@ -137,15 +137,21 @@ function drush_search_api_list() {
   foreach ($indexes as $index) {
     $type = search_api_get_item_type_info($index->item_type);
     $type = isset($type['name']) ? $type['name'] : $index->item_type;
-    $server = $index->server();
-    $server = $server ? $server->name : '(' . t('none') . ')';
+    try {
+      $server = $index->server();
+      $server = $server ? $server->name : '(' . dt('none') . ')';
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+      $server = '(' . dt('unknown: !server', array('server' => $index->server)) . ')';
+    }
     $row = array(
       $index->id,
       $index->name,
       $index->machine_name,
       $server,
       $type,
-      $index->enabled ? t('enabled') : t('disabled'),
+      $index->enabled ? dt('enabled') : dt('disabled'),
       $index->options['cron_limit'],
     );
     $rows[] = $row;
@@ -168,17 +174,24 @@ function drush_search_api_enable($index_id = NULL) {
     return;
   }
   foreach ($indexes as $index) {
+    $vars = array('!index' => $index->name);
     if (!$index->enabled) {
-      drush_log(dt("Enabling index !index and queueing items for indexing.", array('!index' => $index->name)), 'notice');
-      if (search_api_index_enable($index->id)) {
-        drush_log(dt("The index !index was successfully enabled.", array('!index' => $index->name)), 'ok');
+      drush_log(dt("Enabling index !index and queueing items for indexing.", $vars), 'notice');
+      $success = FALSE;
+      try {
+        if ($success = search_api_index_enable($index->id)) {
+          drush_log(dt("The index !index was successfully enabled.", $vars), 'ok');
+        }
       }
-      else {
-        drush_log(dt("Error enabling index !index.", array('!index' => $index->name)), 'error');
+      catch (SearchApiException $e) {
+        drush_log($e->getMessage(), 'error');
+      }
+      if (!$success) {
+        drush_log(dt("Error enabling index !index.", $vars), 'error');
       }
     }
     else {
-      drush_log(dt("The index !index is already enabled.", array('!index' => $index->name)), 'error');
+      drush_log(dt("The index !index is already enabled.", $vars), 'error');
     }
   }
 }
@@ -198,16 +211,23 @@ function drush_search_api_disable($index_id = NULL) {
     return;
   }
   foreach ($indexes as $index) {
+    $vars = array('!index' => $index->name);
     if ($index->enabled) {
-      if (search_api_index_disable($index->id)) {
-        drush_log(dt("The index !index was successfully disabled.", array('!index' => $index->name)), 'ok');
+      $success = FALSE;
+      try {
+        if ($success = search_api_index_disable($index->id)) {
+          drush_log(dt("The index !index was successfully disabled.", $vars), 'ok');
+        }
+      }
+      catch (SearchApiException $e) {
+        drush_log($e->getMessage(), 'error');
       }
-      else {
-        drush_log(dt("Error disabling index !index.", array('!index' => $index->name)), 'error');
+      if (!$success) {
+        drush_log(dt("Error disabling index !index.", $vars), 'error');
       }
     }
     else {
-      drush_log(dt("The index !index is already disabled.", array('!index' => $index->name)), 'error');
+      drush_log(dt("The index !index is already disabled.", $vars), 'error');
     }
   }
 }
@@ -266,7 +286,13 @@ function drush_search_api_index($index_id = NULL, $limit = NULL, $batch_size = N
   }
   foreach ($indexes as $index) {
     // Get the number of remaing items to index.
-    $datasource = $index->datasource();
+    try {
+      $datasource = $index->datasource();
+    }
+    catch (SearchApiException $e) {
+      drush_log($e->getMessage(), 'error');
+      continue;
+    }
     $index_status = $datasource->getIndexStatus($index);
     $remaining = $index_status['total'] - $index_status['indexed'];
     if ($remaining <= 0) {
diff --git a/search_api.install b/search_api.install
index 1d3b204..365279e 100644
--- a/search_api.install
+++ b/search_api.install
@@ -349,8 +349,13 @@ function search_api_enable() {
     }
   }
   foreach ($types as $type => $indexes) {
-    $controller = search_api_get_datasource_controller($type);
-    $controller->startTracking($indexes);
+    try {
+      $controller = search_api_get_datasource_controller($type);
+      $controller->startTracking($indexes);
+    }
+    catch (SearchApiException $e) {
+      watchdog_exception('search_api', $e);
+    }
   }
 }
 
diff --git a/search_api.module b/search_api.module
index abdc951..30d9050 100644
--- a/search_api.module
+++ b/search_api.module
@@ -661,9 +661,21 @@ function search_api_search_api_index_update(SearchApiIndex $index) {
     }
 
     if ($index->server) {
-      $new_server = $index->server(TRUE);
-      // If the server is enabled, we call addIndex(); otherwise, we save the task.
-      $new_server->addIndex($index);
+      try {
+        $new_server = $index->server(TRUE);
+        // If the server is enabled, we call addIndex(); otherwise, we save the task.
+        $new_server->addIndex($index);
+      }
+      catch (SearchApiException $e) {
+        watchdog_exception('search_api', $e);
+        // If the new server doesn't exist, we remove the index from all
+        // servers. Note that saving an entity in its own update hook is usually
+        // a recipe for disaster, but since we are only doing this if a server
+        // is set and remove the server here before saving, it should be safe
+        // enough.
+        $index->server = NULL;
+        $index->save();
+      }
     }
 
     // We also have to re-index all content.
@@ -1097,7 +1109,14 @@ function search_api_track_item_insert($type, array $item_ids) {
     return;
   }
 
-  search_api_get_datasource_controller($type)->trackItemInsert($item_ids, $indexes);
+  try {
+    search_api_get_datasource_controller($type)->trackItemInsert($item_ids, $indexes);
+  }
+  catch (SearchApiException $e) {
+    $vars['%item_type'] = $type;
+    watchdog_exception('search_api', $e, '%type while inserting items of type %item_type: !message in %function (line %line of %file).', $vars);
+    return;
+  }
 
   foreach ($indexes as $index) {
     if (!empty($index->options['index_directly'])) {
@@ -1127,19 +1146,26 @@ function search_api_track_item_change($type, array $item_ids) {
   if (!$indexes) {
     return;
   }
-  search_api_get_datasource_controller($type)->trackItemChange($item_ids, $indexes);
-  foreach ($indexes as $index) {
-    if (!empty($index->options['index_directly'])) {
-      // For indexes with the index_directly option set, queue the items to be
-      // indexed at the end of the request.
-      try {
-        search_api_index_specific_items_delayed($index, $item_ids);
-      }
-      catch (SearchApiException $e) {
-        watchdog_exception('search_api', $e);
+  try {
+    search_api_get_datasource_controller($type)->trackItemChange($item_ids, $indexes);
+    foreach ($indexes as $index) {
+      if (!empty($index->options['index_directly'])) {
+        // For indexes with the index_directly option set, queue the items to be
+        // indexed at the end of the request.
+        try {
+          search_api_index_specific_items_delayed($index, $item_ids);
+        }
+        catch (SearchApiException $e) {
+          watchdog_exception('search_api', $e);
+        }
       }
     }
   }
+  catch (SearchApiException $e) {
+    $vars['%item_type'] = $type;
+    watchdog_exception('search_api', $e, '%type while updating items of type %item_type: !message in %function (line %line of %file).', $vars);
+    return;
+  }
 }
 
 /**
@@ -1157,7 +1183,12 @@ function search_api_track_item_change($type, array $item_ids) {
  *   the Drupal 8 version of this module.
  */
 function search_api_track_item_queued(SearchApiIndex $index, array $item_ids) {
-  $index->datasource()->trackItemQueued($item_ids, $index);
+  try {
+    $index->datasource()->trackItemQueued($item_ids, $index);
+  }
+  catch (SearchApiException $e) {
+    watchdog_exception('search_api', $e);
+  }
 }
 
 /**
@@ -1190,16 +1221,27 @@ function search_api_track_item_delete($type, array $item_ids) {
   );
   $indexes = search_api_index_load_multiple(FALSE, $conditions);
   if ($indexes) {
-    search_api_get_datasource_controller($type)->trackItemDelete($item_ids, $indexes);
+    try {
+      search_api_get_datasource_controller($type)->trackItemDelete($item_ids, $indexes);
+    }
+    catch (SearchApiException $e) {
+      $vars['%item_type'] = $type;
+      watchdog_exception('search_api', $e, '%type while deleting items of type %item_type: !message in %function (line %line of %file).', $vars);
+    }
   }
 
   // Then, delete it from all servers. Servers of disabled indexes have to be
   // considered, too!
   unset($conditions['enabled']);
   foreach (search_api_index_load_multiple(FALSE, $conditions) as $index) {
-    if ($index->server) {
-      $server = $index->server();
-      $server->deleteItems($item_ids, $index);
+    try {
+      if ($server = $index->server()) {
+        $server->deleteItems($item_ids, $index);
+      }
+    }
+    catch (Exception $e) {
+      $vars['%item_type'] = $type;
+      watchdog_exception('search_api', $e, '%type while deleting items of type %item_type: !message in %function (line %line of %file).', $vars);
     }
   }
 }
@@ -1494,10 +1536,7 @@ function search_api_index_specific_items(SearchApiIndex $index, array $ids) {
       // some specific setups.
       $type = search_api_get_item_type_info($index->item_type);
       $type = $type ? $type['name'] : $index->item_type;
-      watchdog('search_api',
-          "Error during indexing: invalid item loaded for @type with ID @id.",
-          array('@id' => $id, '@type' => $type),
-          WATCHDOG_WARNING);
+      watchdog('search_api', "Error during indexing: invalid item loaded for @type with ID @id.", array('@id' => $id, '@type' => $type), WATCHDOG_WARNING);
     }
   }
   $indexed = $items ? $index->index($cloned_items) : array();
@@ -1577,25 +1616,14 @@ function search_api_get_items_to_index(SearchApiIndex $index, $limit = -1) {
  * @param $id
  *   The ID or machine name of the index to execute the search on.
  * @param $options
- *   An associative array of options. The following are recognized:
- *   - filters: Either a SearchApiQueryFilterInterface object or an array of
- *     filters used to filter the search.
- *   - sort: An array of sort directives of the form $field => $order, where
- *     $order is either 'ASC' or 'DESC'.
- *   - offset: The position of the first returned search results relative to the
- *     whole result in the index.
- *   - limit: The maximum number of search results to return. -1 means no limit.
- *   - 'query class': The query class to use. Must be a subtype of
- *     SearchApiQueryInterface.
- *   - conjunction: The type of conjunction to use for this query - either
- *     'AND' or 'OR'. 'AND' by default.
- *   - 'parse mode': The mode with which to parse the $keys variable, if it
- *     is set and not already an array. See SearchApiQuery::parseModes() for
- *     parse modes recognized by the SearchApiQuery class.
- *     Subclasses might define additional modes.
+ *   An associative array of options to be passed to
+ *   SearchApiQueryInterface::__construct().
  *
  * @return SearchApiQueryInterface
  *   An object for searching on the specified index.
+ *
+ * @throws SearchApiException
+ *   If the index is unknown or disabled, or some other error was encountered.
  */
 function search_api_query($id, array $options = array()) {
   $index = search_api_index_load($id);
@@ -1606,9 +1634,10 @@ function search_api_query($id, array $options = array()) {
 }
 
 /**
- * Static store for the searches executed on the current page. Can either be
- * used to store an executed search, or to retrieve a previously stored
- * search.
+ * Stores or retrieves a search executed in this page request.
+ *
+ * Static storage for the searches executed during the current page request. Can
+ * used to store an executed search, or to retrieve a previously stored search.
  *
  * @param $search_id
  *   For pages displaying multiple searches, an optional ID identifying the
@@ -2546,12 +2575,18 @@ function search_api_index_url(SearchApiIndex $index) {
  * @param SearchApiIndex $index
  *   The index whose server should be returned.
  *
- * @return SearchApiServer
+ * @return SearchApiServer|null
  *   The server this index currently resides on, or NULL if the index is
  * currently unassigned.
  */
 function search_api_index_get_server(SearchApiIndex $index) {
-  return $index->server();
+  try {
+    return $index->server();
+  }
+  catch (SearchApiException $e) {
+    watchdog_exception('search_api', $e);
+    return NULL;
+  }
 }
 
 /**
@@ -2628,14 +2663,14 @@ function search_api_index_edit_fields($id, array $fields) {
 /**
  * Enables a search index.
  *
- * @param $id
+ * @param string|int $id
  *   The ID or machine name of the index to enable.
  *
- * @throws SearchApiException
- *   If the index' server isn't enabled.
- *
- * @return
+ * @return int|false
  *   1 on success, 0 or FALSE on failure.
+ *
+ * @throws SearchApiException
+ *   If the index's server doesn't exist.
  */
 function search_api_index_enable($id) {
   $index = search_api_index_load($id, TRUE);
@@ -2646,11 +2681,14 @@ function search_api_index_enable($id) {
 /**
  * Disables a search index.
  *
- * @param $id
+ * @param string|int $id
  *   The ID or machine name of the index to disable.
  *
- * @return
+ * @return int|false
  *   1 on success, 0 or FALSE on failure.
+ *
+ * @throws SearchApiException
+ *   If the index's server doesn't exist.
  */
 function search_api_index_disable($id) {
   $index = search_api_index_load($id, TRUE);
@@ -2803,16 +2841,21 @@ function _search_api_get_items_on_server(SearchApiIndex $index) {
   if (!$index->enabled) {
     return 0;
   }
-  // We want the raw count, without facets or other filters. Therefore we don't
-  // use the query's execute() method but pass it straight to the server for
-  // evaluation. Since this circumvents the normal preprocessing, which sets the
-  // fields (on which some service classes might even rely when there are no
-  // keywords), we set them manually here.
-  $query = $index->query()
-    ->fields(array())
-    ->range(0, 0);
-  $response = $index->server()->search($query);
-  return $response['result count'];
+  try { // We want the raw count, without facets or other filters. Therefore we don't
+    // use the query's execute() method but pass it straight to the server for
+    // evaluation. Since this circumvents the normal preprocessing, which sets the
+    // fields (on which some service classes might even rely when there are no
+    // keywords), we set them manually here.
+    $query = $index->query()
+      ->fields(array())
+      ->range(0, 0);
+    $response = $index->server()->search($query);
+    return $response['result count'];
+  }
+  catch (SearchApiException $e) {
+    watchdog_exception('search_api', $e);
+    return 0;
+  }
 }
 
 /**
diff --git a/search_api.rules.inc b/search_api.rules.inc
index eef4cc0..37143f8 100644
--- a/search_api.rules.inc
+++ b/search_api.rules.inc
@@ -52,6 +52,9 @@ function _search_api_rules_access() {
  * Rules action for indexing an item.
  */
 function _search_api_rules_action_index(EntityDrupalWrapper $wrapper, SearchApiIndex $index = NULL, $index_immediately = TRUE) {
+  // If we do not have an index, we need to guess the item type to use.
+  // @todo Since this can only be used with entities anyways, we can just loop
+  //   over the item type information and use all types with that entity type.
   $type = $wrapper->type();
   $item_ids = array($wrapper->getIdentifier());
 
@@ -61,6 +64,7 @@ function _search_api_rules_action_index(EntityDrupalWrapper $wrapper, SearchApiI
   }
 
   if ($index) {
+    $type = $index->item_type;
     $indexes = array($index);
   }
   else {
