diff --git a/fsl/utils/idle.py b/fsl/utils/idle.py
index bef726633b40f8977a3a77a429d77917f7c398b0..f8ff25349c3b3bc01465dfb9a1ebba584abf543d 100644
--- a/fsl/utils/idle.py
+++ b/fsl/utils/idle.py
@@ -759,10 +759,11 @@ class Task(object):
     """Container object which encapsulates a task that is run by a
     :class:`TaskThread`.
     """
-    def __init__(self, name, func, onFinish, args, kwargs):
+    def __init__(self, name, func, onFinish, onError, args, kwargs):
         self.name     = name
         self.func     = func
         self.onFinish = onFinish
+        self.onError  = onError
         self.args     = args
         self.kwargs   = kwargs
         self.enabled  = True
@@ -808,9 +809,16 @@ class TaskThread(threading.Thread):
 
         :arg onFinish: An optional function to be called (via :func:`idle`)
                        when the task funtion has finished. Must be provided as
-                       a keyword argument. If the ``func`` raises a
-                       :class`TaskThreadVeto` error, this function will not
-                       be called.
+                       a keyword argument, and must itself accept no arguments.
+                       If the ``func`` raises a :class`TaskThreadVeto` error,
+                       this function will not be called.
+
+        :arg onError:  An optional function to be called (via :func:`idle`)
+                       if the task funtion raises an ``Exception``. Must be
+                       provided as a keyword argument, and must itself accept
+                       the raised ``Exception`` object as a single argument.
+                       If the ``func`` raises a :class`TaskThreadVeto` error,
+                       this function will not be called.
 
         All other arguments are passed through to the task function when it is
         executed.
@@ -821,16 +829,18 @@ class TaskThread(threading.Thread):
                   results.
 
         .. warning:: Make sure that your task function is not expecting keyword
-                     arguments called ``taskName`` or ``onFinish``!
+                     arguments called ``taskName``, ``onFinish``, or
+                     ``onError``!
         """
 
         name     = kwargs.pop('taskName', None)
         onFinish = kwargs.pop('onFinish', None)
+        onError  = kwargs.pop('onError',  None)
 
         log.debug('Enqueueing task: {} [{}]'.format(
             name, getattr(func, '__name__', '<unknown>')))
 
-        t = Task(name, func, onFinish, args, kwargs)
+        t = Task(name, func, onFinish, onError, args, kwargs)
         self.__enqueued[name] = t
         self.__q.put(t)
 
@@ -951,6 +961,9 @@ class TaskThread(threading.Thread):
                     type(e).__name__,
                     str(e)),
                     exc_info=True)
+                if task.onError is not None:
+                    idle(task.onError, e)
+
             finally:
                 self.__q.task_done()