diff --git pdns/axfr-retriever.cc pdns/axfr-retriever.cc
index f2630c9ae..a135b113f 100644
--- pdns/axfr-retriever.cc
+++ pdns/axfr-retriever.cc
@@ -123,50 +123,48 @@ int AXFRRetriever::getChunk(Resolver::res_t &res, vector<DNSRecord>* records, ui
 
   timeoutReadn(len, timeout);
 
   d_receivedBytes += (uint16_t) len;
 
-  MOADNSParser mdp(false, d_buf.data(), len);
-
-  int err = mdp.d_header.rcode;
+  try {
+    MOADNSParser mdp(false, d_buf.data(), len);
 
-  if(err) {
-    throw ResolverException("AXFR chunk error: " + RCode::to_s(err));
-  }
+    int err = mdp.d_header.rcode;
+    if (err != 0) {
+      throw ResolverException("AXFR chunk error: " + RCode::to_s(err));
+    }
 
-  if(mdp.d_header.tc) {
-    throw ResolverException("AXFR chunk had TC bit set");
-  }
+    if(mdp.d_header.tc) {
+      throw ResolverException("AXFR chunk had TC bit set");
+    }
 
-  try {
     d_tsigVerifier.check(std::string(d_buf.data(), len), mdp);
-  }
-  catch(const std::runtime_error& re) {
-    throw ResolverException(re.what());
-  }
 
-  if(!records) {
-    err = parseResult(mdp, DNSName(), 0, 0, &res);
+    if (records == nullptr) {
+      err = parseResult(mdp, DNSName(), 0, 0, &res);
+      if (err == 0) {
+        for(const auto& answer :  mdp.d_answers)
+          if (answer.first.d_type == QType::SOA)
+            d_soacount++;
+      }
+    }
+    else {
+      records->clear();
+      records->reserve(mdp.d_answers.size());
 
-    if (!err) {
-      for(const auto& answer :  mdp.d_answers)
-        if (answer.first.d_type == QType::SOA)
+      for(auto& r: mdp.d_answers) {
+        if (r.first.d_type == QType::SOA) {
           d_soacount++;
-    }
-  }
-  else {
-    records->clear();
-    records->reserve(mdp.d_answers.size());
+        }
 
-    for(auto& r: mdp.d_answers) {
-      if (r.first.d_type == QType::SOA) {
-        d_soacount++;
+        records->push_back(std::move(r.first));
       }
-
-      records->push_back(std::move(r.first));
     }
   }
+  catch(const std::runtime_error& re) {
+    throw ResolverException(re.what());
+  }
 
   return true;
 }
 
 void AXFRRetriever::timeoutReadn(uint16_t bytes, uint16_t timeoutsec)
diff --git pdns/comfun.cc pdns/comfun.cc
index 01a1fff2c..e2e046c7a 100644
--- pdns/comfun.cc
+++ pdns/comfun.cc
@@ -548,8 +548,11 @@ try
   else {
     cerr<<"Unknown mode "<<argv[1]<<endl;
   }
   //  cout<<g_mtracer->topAllocatorsString(20)<<endl;
 }
-catch(PDNSException& pe) {
-  cerr<<"Fatal error: "<<pe.reason<<endl;
+catch(const PDNSException& exc) {
+  cerr<<"Fatal error: "<<exc.reason<<endl;
+}
+catch(const std::exception& exc) {
+  cerr<<"Fatal error: "<<exc.what()<<endl;
 }
diff --git pdns/dnspacket.cc pdns/dnspacket.cc
index 7c664db34..e6e4cc117 100644
--- pdns/dnspacket.cc
+++ pdns/dnspacket.cc
@@ -505,64 +505,81 @@ void DNSPacket::setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyna
   d_tsigtimersonly=timersonly;
 }
 
 bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_t* tsigPosOut) const
 {
-  MOADNSParser mdp(d_isQuery, d_rawpacket);
-  uint16_t tsigPos = mdp.getTSIGPos();
-  if(!tsigPos)
-    return false;
+  try {
+    MOADNSParser mdp(d_isQuery, d_rawpacket);
+    uint16_t tsigPos = mdp.getTSIGPos();
+    if (tsigPos == 0) {
+      return false;
+    }
 
-  bool gotit=false;
-  for(const auto & answer : mdp.d_answers) {
-    if(answer.first.d_type == QType::TSIG && answer.first.d_class == QType::ANY) {
-      // cast can fail, f.e. if d_content is an UnknownRecordContent.
-      auto content = getRR<TSIGRecordContent>(answer.first);
-      if (!content) {
-        g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
-        return false;
+    bool gotit=false;
+    for(const auto & answer : mdp.d_answers) {
+      if(answer.first.d_type == QType::TSIG && answer.first.d_class == QType::ANY) {
+        // cast can fail, f.e. if d_content is an UnknownRecordContent.
+        auto content = getRR<TSIGRecordContent>(answer.first);
+        if (!content) {
+          g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
+          return false;
+        }
+        *trc = *content;
+        *keyname = answer.first.d_name;
+        gotit=true;
       }
-      *trc = *content;
-      *keyname = answer.first.d_name;
-      gotit=true;
     }
+    if(!gotit)
+      return false;
+
+    if (tsigPosOut != nullptr) {
+      *tsigPosOut = tsigPos;
+    }
+
+    return true;
   }
-  if(!gotit)
+  catch (const MOADNSException&) {
+    // If execution has reached this routine, we can reasonably assume that
+    // the packet is good enough to pass the sanity checks of
+    // MOADNSParser::init(). But just in case it doesn't, better handle this.
     return false;
-
-  if (tsigPosOut) {
-    *tsigPosOut = tsigPos;
   }
-
-  return true;
 }
 
 bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
 {
-  MOADNSParser mdp(d_isQuery, d_rawpacket);
-  bool gotit=false;
-
-  for(const auto & answer : mdp.d_answers) {
-    if (gotit) {
-      g_log<<Logger::Error<<"More than one TKEY record found in query"<<endl;
-      return false;
-    }
+  try {
+    MOADNSParser mdp(d_isQuery, d_rawpacket);
+    bool gotit=false;
 
-    if(answer.first.d_type == QType::TKEY) {
-      // cast can fail, f.e. if d_content is an UnknownRecordContent.
-      auto content = getRR<TKEYRecordContent>(answer.first);
-      if (!content) {
-        g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
+    for(const auto & answer : mdp.d_answers) {
+      if (gotit) {
+        g_log<<Logger::Error<<"More than one TKEY record found in query"<<endl;
         return false;
       }
-      *tr = *content;
-      *keyname = answer.first.d_name;
-      gotit=true;
+
+      if(answer.first.d_type == QType::TKEY) {
+        // cast can fail, f.e. if d_content is an UnknownRecordContent.
+        auto content = getRR<TKEYRecordContent>(answer.first);
+        if (!content) {
+          g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
+          return false;
+        }
+        *tr = *content;
+        *keyname = answer.first.d_name;
+        gotit=true;
+      }
     }
-  }
 
-  return gotit;
+    return gotit;
+  }
+  catch (const MOADNSException&) {
+    // If execution has reached this routine, we can reasonably assume that
+    // the packet is good enough to pass the sanity checks of
+    // MOADNSParser::init(). But just in case it doesn't, better handle this.
+    return false;
+  }
 }
 
 /** This function takes data from the network, possibly received with recvfrom, and parses
     it into our class. Results of calling this function multiple times on one packet are
     unknown. Returns -1 if the packet cannot be parsed.
diff --git pdns/resolver.cc pdns/resolver.cc
index 28db4e65e..36e239e51 100644
--- pdns/resolver.cc
+++ pdns/resolver.cc
@@ -265,46 +265,56 @@ bool Resolver::tryGetSOASerial(DNSName *domain, ComboAddress* remote, uint32_t *
       return false;
 
     throw ResolverException("recvfrom error waiting for answer: "+stringerror());
   }
 
-  MOADNSParser mdp(false, (char*)buf, err);
-  *id=mdp.d_header.id;
-  *domain = mdp.d_qname;
-
-  if(domain->empty())
-    throw ResolverException("SOA query to '" + remote->toLogString() + "' produced response without domain name (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")");
-
-  if(mdp.d_answers.empty())
-    throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' produced no results (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")");
-
-  if(mdp.d_qtype != QType::SOA)
-    throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned wrong record type");
-
-  if(mdp.d_header.rcode != 0)
-    throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned Rcode " + RCode::to_s(mdp.d_header.rcode));
-
-  *theirInception = *theirExpire = 0;
-  bool gotSOA=false;
-  for(const MOADNSParser::answers_t::value_type& drc :  mdp.d_answers) {
-    if(drc.first.d_type == QType::SOA && drc.first.d_name == *domain) {
-      auto src = getRR<SOARecordContent>(drc.first);
-      if (src) {
-        *theirSerial = src->d_st.serial;
-        gotSOA = true;
-      }
+  bool gotSOA{false};
+  try {
+    MOADNSParser mdp(false, (char*)buf, err);
+    *id=mdp.d_header.id;
+    *domain = mdp.d_qname;
+
+    if(domain->empty()) {
+      throw ResolverException("SOA query to '" + remote->toLogString() + "' produced response without domain name (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")");
+    }
+
+    if(mdp.d_answers.empty()) {
+      throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' produced no results (RCode: " + RCode::to_s(mdp.d_header.rcode) + ")");
+    }
+
+    if(mdp.d_qtype != QType::SOA) {
+      throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned wrong record type");
     }
-    if(drc.first.d_type == QType::RRSIG && drc.first.d_name == *domain) {
-      auto rrc = getRR<RRSIGRecordContent>(drc.first);
-      if(rrc && rrc->d_type == QType::SOA) {
-        *theirInception= std::max(*theirInception, rrc->d_siginception);
-        *theirExpire = std::max(*theirExpire, rrc->d_sigexpire);
+
+    if(mdp.d_header.rcode != 0) {
+      throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' returned Rcode " + RCode::to_s(mdp.d_header.rcode));
+    }
+
+    *theirInception = *theirExpire = 0;
+    for(const MOADNSParser::answers_t::value_type& drc :  mdp.d_answers) {
+      if(drc.first.d_type == QType::SOA && drc.first.d_name == *domain) {
+        auto src = getRR<SOARecordContent>(drc.first);
+        if (src) {
+          *theirSerial = src->d_st.serial;
+          gotSOA = true;
+        }
+      }
+      if(drc.first.d_type == QType::RRSIG && drc.first.d_name == *domain) {
+        auto rrc = getRR<RRSIGRecordContent>(drc.first);
+        if(rrc && rrc->d_type == QType::SOA) {
+          *theirInception= std::max(*theirInception, rrc->d_siginception);
+          *theirExpire = std::max(*theirExpire, rrc->d_sigexpire);
+        }
       }
     }
   }
-  if(!gotSOA)
+  catch (const MOADNSException& exc) {
+    throw ResolverException("SOA Query to '" + remote->toLogString() + "' produced ill-formed response: " + exc.what());
+  }
+  if(!gotSOA) {
     throw ResolverException("Query to '" + remote->toLogString() + "' for SOA of '" + domain->toLogString() + "' did not return a SOA");
+  }
   return true;
 }
 
 int Resolver::resolve(const ComboAddress& to, const DNSName &domain, int type, Resolver::res_t* res, const ComboAddress &local)
 {
@@ -335,10 +345,13 @@ int Resolver::resolve(const ComboAddress& to, const DNSName &domain, int type, R
     return parseResult(mdp, domain, type, id, res);
   }
   catch(ResolverException &re) {
     throw ResolverException(re.reason+" from "+to.toLogString());
   }
+  catch (const MOADNSException& exc) {
+    throw ResolverException(std::string(exc.what()) + " from " + to.toLogString());
+  }
 }
 
 int Resolver::resolve(const ComboAddress& ipport, const DNSName &domain, int type, Resolver::res_t* res) {
   ComboAddress local;
   local.sin4.sin_family = 0;
diff --git pdns/stubresolver.cc pdns/stubresolver.cc
index 84cdca320..c18d1f42b 100644
--- pdns/stubresolver.cc
+++ pdns/stubresolver.cc
@@ -169,25 +169,31 @@ int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSZoneRecord>& r
       }
     }
     catch (...) {
       continue;
     }
-    MOADNSParser mdp(false, reply);
-    if (mdp.d_header.rcode == RCode::ServFail) {
-      continue;
-    }
+    try {
+      MOADNSParser mdp(false, reply);
+      if (mdp.d_header.rcode == RCode::ServFail) {
+        continue;
+      }
 
-    for (const auto& answer : mdp.d_answers) {
-      if (answer.first.d_place == 1 && answer.first.d_type == qtype) {
-        DNSZoneRecord zrr;
-        zrr.dr = answer.first;
-        zrr.auth = true;
-        ret.push_back(zrr);
+      for (const auto& answer : mdp.d_answers) {
+        if (answer.first.d_place == 1 && answer.first.d_type == qtype) {
+          DNSZoneRecord zrr;
+          zrr.dr = answer.first;
+          zrr.auth = true;
+          ret.push_back(std::move(zrr));
+        }
       }
+      g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got answered by " << dest.toString() << endl;
+      return mdp.d_header.rcode;
+    }
+    catch (const MOADNSException& exc) {
+      g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got ill-formed answer from " << dest.toString() << ": " << exc.what() << endl;
+      continue;
     }
-    g_log << Logger::Debug << logPrefix << "Question for '" << queryNameType << "' got answered by " << dest.toString() << endl;
-    return mdp.d_header.rcode;
   }
   return RCode::ServFail;
 }
 
 int stubDoResolve(const DNSName& qname, uint16_t qtype, vector<DNSRecord>& ret, const EDNSSubnetOpts* d_eso)
