diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
index 806abfd022d81c18e47559026d19ad243b1b27a3..49c56a2e137775e9ec9a616e302272f501fa7342 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReducer.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "./FastReducer.h"
@@ -141,22 +141,23 @@ bool FastReducer::findInitialJetGroups(const std::vector<int>& leaves,
   /*
     Will now test the incoming jet groups against the leaf conditions.
   */
-
+  
   std::size_t ijg{0};
   for(auto iter = groups_b; iter != groups_e; ++iter){
     auto jg = *iter;
     
     if(jg.size() != 1){
-      collector->collect("FastReducer", "No jet groups");
+      collector->collect("FastReducer", "Initial jet group size != 1");
       return false;
     }
-
-    // if a jet group satisfies a condition, note the fact, and store it by index
+    
+    // if a jet group satisfies a condition, note the fact,
+    // and store it by index
     bool jg_used{false};
     
     auto cur_jg = m_jgIndAllocator(std::vector<std::size_t>{ijg});
     for(const auto& leaf: leaves){
-
+      
       m_testedBy[leaf].insert(cur_jg);
       if (m_conditions[leaf]->isSatisfied(jg, collector)){
 	  jg_used= true;
@@ -177,16 +178,56 @@ bool FastReducer::findInitialJetGroups(const std::vector<int>& leaves,
       recordJetGroup(p.first, p.second, collector);
     }
   }
-  
+
   // check all leaf conditions are satisfied
   for (const auto& i : leaves) {
-    if ((m_satisfiedBy.at(i)).empty()) { return false; }
+    auto& satisfiedBy = m_satisfiedBy.at(i);
+    if (satisfiedBy.empty()) {
+      return false;
+    }
   }
-  
-  return true;
-}
 
+  /*
+    For the special but important case where all leaf nodes have
+    the root node as a parent, check that there are enough jets
+    to pass the hypo. This prevents doing a long calculation 
+    to discover that the hypo will fail. For example, if the chain
+    requires 10j40, and there are 5 jets that pass the condition,
+    each condition will be satisfied by th 5 jets, and 5^10 combinations
+    will be attempted in th seach for a successful combination. As there
+    are only 5 jets involved, such a combination does not exist.
+
+    Such trees have a tree vector with all entries == 0.
+
+    This check cannot be applied in the general case. For example,
+    if the root condition requires 4 jets, and has three children,
+    two of which are leaf nodes, while the other is not, then the
+    check will fail the event as no jets have yet ben assigned to the
+    second child, while the full popagation through the tree may pass the
+    event.
+
+    A possible way to tighten the chck would be to forbid children to be
+    separated from thir parent by more than 1 generation.
+  */
 
+  if (std::all_of(m_tree.cbegin(),
+		  m_tree.cend(),
+		  [](std::size_t i){return i == 0;})) {
+
+    if (m_conditions[0]->capacity() > ijg) {
+      
+      if (collector){
+	collector->collect("FastReducer", "too few children. root capacity "
+			   + std::to_string(m_conditions[0]->capacity()) +
+			   " no of children: " + std::to_string(ijg));
+      }
+
+      return false;
+    }
+  }
+  
+  return true;
+}  
 
 bool FastReducer::propagateJetGroups(const Collector& collector){
   
@@ -218,6 +259,7 @@ bool FastReducer::propagateJetGroups(const Collector& collector){
   }
   
   while(!to_process.empty()){
+
     auto k = to_process.top();
     to_process.pop();
 
@@ -269,7 +311,7 @@ bool FastReducer::propagate_(std::size_t child,
   // Edges are contructed between satisfying jet groups and the parent.
   // if any such edge is constructed, the calling rroutine is notified so it
   // can scheduling processing the parent as a child.
-
+        
   std::size_t par =  m_tree.parent(child);
 
   // child == 0  do not attempt to process parent of node.
@@ -282,11 +324,12 @@ bool FastReducer::propagate_(std::size_t child,
   // eg if condition c1 is satisfied by jg11 and jg12, while its only
   // sibling c2 is satisfied by jg21, the external jet groups are
   // jg11jg21, jg12jg21. Each of these  are flattened.
-  
+
+   
   auto jg_product = JetGroupProduct(siblings, m_satisfiedBy);
-  
+   
   // obtain the next product of hob groups passing siblings
-  auto next = jg_product.next();
+  auto next = jg_product.next(collector);
 
   // step through the jet groups found by combining ghe child groups
   // check ecach combination to see if it satisfies the parent. If so
@@ -316,7 +359,7 @@ bool FastReducer::propagate_(std::size_t child,
     std::set<std::size_t> unique_indices(elem_jgs.begin(),
 					 elem_jgs.end());
     if(unique_indices.size() != elem_jgs.size()){
-      next = jg_product.next();
+      next = jg_product.next(collector);
       continue;
     }
 
@@ -325,7 +368,7 @@ bool FastReducer::propagate_(std::size_t child,
     // obtain an index for the new jet group.
     auto cur_jg = m_jgIndAllocator(elem_jgs);
     if(m_testedBy[par].find(cur_jg) != m_testedBy[par].end()){
-      next = jg_product.next();
+      next = jg_product.next(collector);
       continue;
     }
     m_testedBy[par].insert(cur_jg);
@@ -344,7 +387,7 @@ bool FastReducer::propagate_(std::size_t child,
       if(collector){recordJetGroup(cur_jg, jg, collector);}
     }
     
-    next = jg_product.next();
+    next = jg_product.next(collector);
   }
 
   if(collector and !par_satisfied){
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
index f5ca74952ced2bd30086d14c243512d770086c80..7f78b0ca100e5cb2af754bdabb1184881526a309 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/FastReductionMatcher.cxx
@@ -47,7 +47,7 @@ FastReductionMatcher::match(const HypoJetGroupCIter& groups_b,
                       m_conditions,
                       m_tree,
                       m_sharedNodes,
-		      jetCollector,
+                      jetCollector,
                       collector);
 
   return std::make_optional<bool>(reducer.pass());
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx
index e660ab55479b6367edce21a64097b7e6b646c608..21ce1a5e774698b2e0e4b09ee5ba7cde03866954 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.cxx
@@ -4,6 +4,7 @@
 
 #include "./JetGroupProduct.h"
 #include <set>
+#include <string>
 
 
 JetGroupProduct::JetGroupProduct(const std::vector<std::size_t>& siblings,
@@ -22,9 +23,18 @@ JetGroupProduct::JetGroupProduct(const std::vector<std::size_t>& siblings,
   m_productGen = ProductGen(ends);
 }
   
-std::optional<std::vector<std::size_t>> JetGroupProduct::next(){
+std::optional<std::vector<std::size_t>>
+JetGroupProduct::next(const Collector& collector){
 
+  unsigned int ipass{0};
+  
   while(true){
+    
+    if(collector){
+	  collector->collect("JobGroupProduct::next()",
+                         "loop start pass" + std::to_string(ipass++));
+	}
+      
     auto opt_indices = m_productGen.next();
     if(!opt_indices.has_value()){
       return std::optional<std::vector<std::size_t>>();
@@ -33,8 +43,8 @@ std::optional<std::vector<std::size_t>> JetGroupProduct::next(){
     // indices index job groups in the indJetGroups table
     auto indices = *opt_indices;
 
-    // select inicies from the child jet group inicies. Form a vector
-    // of inidices.
+    // select indicies from the child jet group indicies. Form a vector
+    // of indices.
     std::vector<std::size_t> jg_indices;
     for(std::size_t i = 0; i < indices.size(); ++i){
       auto s = m_siblings[i];
@@ -44,7 +54,7 @@ std::optional<std::vector<std::size_t>> JetGroupProduct::next(){
     }
 
     
-    // require there are no duplicate inidices - this would be
+    // require there are no duplicate indices - this would be
     // rejected  by a non-sharing flow network. but remove the
     // case early. Sharing is handled otherwise...
     std::set<std::size_t> unique_indices(jg_indices.begin(),
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h
index dc31dc0772dcdfa331fe775feb5f9e64fa369eb6..0e51a85da75d0d2ba2807a1d8586062b4cfbc797 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/JetGroupProduct.h
@@ -6,12 +6,15 @@
 #define TRIGHLTJETHYPO_JETGROUPPRODUCT_H
 
 #include "./ProductGen.h"
+#include "./DebugInfoCollector.h"
 #include "TrigHLTJetHypo/TrigHLTJetHypoUtils/HypoJetDefs.h"
 #include <vector>
 #include <optional>
 
 using CondInd2JetGroupsInds = std::map<int, std::vector<std::size_t>>;
 
+typedef std::unique_ptr<ITrigJetHypoInfoCollector> Collector;
+
 class JetGroupProduct{
   /*
    * Iterate through the combinations of jet groups.
@@ -29,7 +32,7 @@ class JetGroupProduct{
  public:
   JetGroupProduct(const std::vector<std::size_t>& siblings,
 		  const CondInd2JetGroupsInds& satisfiedBy);
-  std::optional<std::vector<std::size_t>> next();
+  std::optional<std::vector<std::size_t>> next(const Collector&);
   
  private:
   const std::vector<std::size_t> m_siblings;
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tracer.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tracer.h
new file mode 100644
index 0000000000000000000000000000000000000000..796815b49b31aaf399da95718a3a8e695f057b93
--- /dev/null
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tracer.h
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGJETHYPO_TRACER_H
+#define TRIGJETHYPO_TRACER_H
+
+#include <iostream>
+class Tracer {
+public:
+  Tracer(const std::string& msg): m_msg(msg){
+    std::cerr<< "+ " << m_msg << '\n';} 
+  ~Tracer() {
+    std::cerr << "- " <<m_msg << '\n';
+  }
+private:
+  std::string m_msg;
+};
+
+#endif
diff --git a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tree.h b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tree.h
index 06df1b161800954cb23bffd5ec95d944e0439a30..9cc78bfc9bf007ed067240841c6c1768a30fcdee 100644
--- a/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tree.h
+++ b/Trigger/TrigHypothesis/TrigHLTJetHypo/src/Tree.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef TRIGHLTJETHYPO_TREE_H
@@ -25,6 +25,17 @@ class Tree{
   const std::vector<std::size_t>& leaves() const;
   const std::vector<std::size_t>& firstGeneration() const;
 
+  std::vector<std::size_t>::const_iterator cbegin() const {
+    return m_parents.cbegin();
+  }
+
+
+  std::vector<std::size_t>::const_iterator cend() const {
+    return m_parents.cend();
+  }
+
+
+
   std::size_t depth(std::size_t) const;
 
  private: