diff --git a/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql b/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql
index 88b4de934e957a839746e850d92ff3ce37d4c371..87f9da9d4a0c5431fe3026d1559a4de8a41ae9d1 100644
--- a/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql
+++ b/product/CMFActivity/skins/activity/SQLDict_hasMessage.zsql
@@ -8,13 +8,13 @@ class_name:
 class_file:
 </dtml-comment>
 <params>path
-method_id</params>
+method_id
+only_valid</params>
 SELECT count(path) as message_count FROM
   message
-<dtml-if "path or method_id"> 
 WHERE
-<dtml-if path>  path = <dtml-sqlvar path type="string"></dtml-if>
+1 = 1
+<dtml-if path> AND path = <dtml-sqlvar path type="string"></dtml-if>
 <dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if>
-</dtml-if>
+<dtml-if only_valid>AND processing_node > -2</dtml-if>
 
-  
diff --git a/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql b/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql
index 734a114414c8a86440969734ec15b032c452e48d..8302bd328c198c7c7d989df4cc4c4e273a1992bb 100644
--- a/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql
+++ b/product/CMFActivity/skins/activity/SQLQueue_hasMessage.zsql
@@ -8,12 +8,13 @@ class_name:
 class_file:
 </dtml-comment>
 <params>path
-method_id</params>
+method_id
+only_valid</params>
 SELECT count(path) as message_count FROM
   message_queue
-<dtml-if "path or method_id"> 
 WHERE
-<dtml-if path>  path = <dtml-sqlvar path type="string"></dtml-if>
+1 = 1
+<dtml-if path>AND path = <dtml-sqlvar path type="string"></dtml-if>
 <dtml-if method_id>AND method_id = <dtml-sqlvar method_id type="string"></dtml-if>
-</dtml-if>
-  
+<dtml-if only_valid>AND processing_node > -2</dtml-if>
+
diff --git a/product/ERP5/Document/Alarm.py b/product/ERP5/Document/Alarm.py
index f0c033df701de8b106e821574dc219516d689fdc..a8c5993668e3944e4e3275c0da606a2bd6787800 100644
--- a/product/ERP5/Document/Alarm.py
+++ b/product/ERP5/Document/Alarm.py
@@ -264,7 +264,7 @@ class Alarm(XMLObject, PeriodicityMixin):
     active or not. It is activated when it is doing some calculation with
     activeSense or solve.
     """
-    return self.hasActivity()
+    return self.hasActivity(only_valid=1)
 
   security.declareProtected(Permissions.ModifyPortalContent, 'activeSense')
   def activeSense(self):
diff --git a/product/ERP5/tests/testAlarm.py b/product/ERP5/tests/testAlarm.py
index d8bb74a87be6c38c15552bea3cd11184b77817f9..a0fdba61b1e24a5d32c4c9ff36245af3cefbb805 100644
--- a/product/ERP5/tests/testAlarm.py
+++ b/product/ERP5/tests/testAlarm.py
@@ -421,7 +421,51 @@ class TestAlarm(ERP5TypeTestCase):
     get_transaction().commit()
     self.tic()
     self.assertEquals(active_process, alarm.getLastActiveProcess())
- 
+
+  def test_15_FailedAlarmsDoNotBlockFutureAlarms(self, quiet=0, run=run_all_test):
+    if not run: return
+    if not quiet:
+      message = 'Test Failed Alarms Do Not Block Future Alarms'
+      ZopeTestCase._print('\n%s ' % message)
+      LOG('Testing... ',0,message)
+    sense_method_id = 'Alarm_testSenseMethod'
+    skin_folder_id = 'custom'
+    skin_folder = self.getPortal().portal_skins[skin_folder_id]
+    skin_folder.manage_addProduct['PythonScripts'].manage_addPythonScript(id=sense_method_id)
+    # Make the sense method fail
+    skin_folder[sense_method_id].ZPythonScript_edit('*args,**kw', 'raise Exception')
+    del skin_folder
+    alarm = self.newAlarm()
+    now = DateTime()
+    alarm.setActiveSenseMethodId(sense_method_id)
+    self.assertEquals(alarm.isActive(), 0)
+    alarm.activeSense()
+    get_transaction().commit()
+    try:
+      self.tic()
+    except RuntimeError:
+      pass
+    else:
+      raise Exception, 'Tic did not raise though activity was supposed to fail'
+    # Check that the alarm is not considered active, although there is a remaining activity.
+    self.assertEquals(alarm.hasActivity(), 1)
+    self.assertEquals(alarm.isActive(), 0)
+    self.assertEquals(alarm.getLastActiveProcess(), None)
+    # Make the sense method succeed and leave a trace
+    self.getPortal().portal_skins[skin_folder_id][sense_method_id].ZPythonScript_edit('*args,**kw', 'context.newActiveProcess()')
+    alarm.activeSense()
+    get_transaction().commit()
+    # Note: this call to tic will not fail, because the same method on the same
+    # object is activated again in SQLDict. When the new message will be
+    # -successfully- processed, the previous -failed- message will get removed
+    # in the cleanup. This behaviour is logical if we consider that manually
+    # executing the failed message to get the error will lead to no error.
+    # But it can also be considered illogical if failed messages are supposed
+    # to be preserved for future analysis.
+    self.tic()
+    # Chen that the second alarm execution did happen
+    self.assertNotEquals(alarm.getLastActiveProcess(), None)
+
 if __name__ == '__main__':
     framework()
 else: