diff --git a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/CMakeLists.txt b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/CMakeLists.txt
index 8663ec5a1fe553202b26c7bf7b38dcdb5e67dd60..cde4cd61a5f3ea01face700c16b1b0e4a12fef22 100644
--- a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/CMakeLists.txt
+++ b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/CMakeLists.txt
@@ -14,8 +14,11 @@ atlas_depends_on_subdirs( PUBLIC
                           Tracking/TrkTools/TrkToolInterfaces
                           PRIVATE
                           DetectorDescription/AtlasDetDescr
+                          DetectorDescription/GeoModel/GeoModelInterfaces
                           DetectorDescription/Identifier
                           InnerDetector/InDetConditions/InDetConditionsSummaryService
+                          InnerDetector/InDetConditions/SCT_ConditionsServices
+                          InnerDetector/InDetDetDescr/InDetIdentifier
                           InnerDetector/InDetDetDescr/InDetReadoutGeometry
                           InnerDetector/InDetRecTools/InDetRecToolInterfaces
                           Tracking/TrkDetDescr/TrkDetDescrUtils
diff --git a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/InDetTrackHoleSearch/InDetTrackHoleSearchTool.h b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/InDetTrackHoleSearch/InDetTrackHoleSearchTool.h
index 7a6fffaf016fac92368aaa661d0f2cab4a86143f..6e36c0b4d1082086575b27d38f47e2353bdf9b63 100644
--- a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/InDetTrackHoleSearch/InDetTrackHoleSearchTool.h
+++ b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/InDetTrackHoleSearch/InDetTrackHoleSearchTool.h
@@ -19,14 +19,20 @@
 #include <map>
 
 class AtlasDetectorID;
+class SCT_ID;
 class Identifier;
 class AtlasID;
 class IInDetConditionsSvc;
+class ISCT_ConfigurationConditionsSvc;
+class ISCT_ByteStreamErrorsSvc;
 namespace InDet {class IInDetTestPixelLayerTool; }
+class IGeoModelSvc;
 
 namespace Trk { class RIO_OnTrack; class TrackStateOnSurface; class Track;}
 namespace Trk { class IExtrapolator;}
 
+namespace InDetDD { class SiDetectorElement; }
+
 namespace InDet 
 {
 
@@ -111,6 +117,15 @@ namespace InDet
       /** Handles to IConditionsSummaryServices for Pixels and SCT*/
       ServiceHandle <IInDetConditionsSvc> m_pixelCondSummarySvc, m_sctCondSummarySvc;
       ToolHandle< IInDetTestPixelLayerTool >  m_pixelLayerTool;
+      ServiceHandle <ISCT_ConfigurationConditionsSvc> m_sctConfCondSvc;
+
+      /** Handle to ISCT_ByteStreamErrorsSvc*/
+      ServiceHandle <ISCT_ByteStreamErrorsSvc> m_sctBsErrSvc;
+
+      /** Handle for IGeoModelSvc to retrieve geo model information */
+      ServiceHandle<IGeoModelSvc> m_geoModelSvc;
+
+      const SCT_ID* m_sct_id;
 
       /** Configure outwards hole search */
       bool m_extendedListOfHoles,m_cosmic;
@@ -118,6 +133,9 @@ namespace InDet
       /** Control usage of pixel, SCT and TRT info */
       bool m_usepix, m_usesct;
 
+      /** Control check of bad SCT chip (should be false for ITk Strip) */
+      bool m_checkBadSCTChip;
+
       /** Min number of hits **/
       int m_minSiHits;
 
@@ -169,6 +187,8 @@ namespace InDet
       const Trk::Track*  addHolesToTrack(const Trk::Track& oldTrack, 
 					 std::vector<const Trk::TrackStateOnSurface*>* listOfHoles) const;
 
+      /** This method checks the SCT ABCD chip where the track passes through is bad or not */
+      bool isBadSCTChip(const Identifier& waferId, const Trk::TrackParameters& parameters, const InDetDD::SiDetectorElement& siElement) const;
     };
 
 } // end of namespace
diff --git a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/src/InDetTrackHoleSearchTool.cxx b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/src/InDetTrackHoleSearchTool.cxx
index 33b07500ea0d744df21ee2aa3128b57af65dbee8..a3dca9c31e57f41d2221ab4ddbcb860d68638e0d 100644
--- a/InnerDetector/InDetRecTools/InDetTrackHoleSearch/src/InDetTrackHoleSearchTool.cxx
+++ b/InnerDetector/InDetRecTools/InDetTrackHoleSearch/src/InDetTrackHoleSearchTool.cxx
@@ -21,12 +21,16 @@
 #include "TrkDetDescrUtils/SharedObject.h"
 #include "TrkGeometry/TrackingVolume.h"
 #include "Identifier/Identifier.h"
+#include "InDetIdentifier/SCT_ID.h"
 #include "AtlasDetDescr/AtlasDetectorID.h"
 #include "InDetConditionsSummaryService/IInDetConditionsSvc.h"
+#include "SCT_ConditionsServices/ISCT_ConfigurationConditionsSvc.h"
+#include "SCT_ConditionsServices/ISCT_ByteStreamErrorsSvc.h"
 #include "InDetReadoutGeometry/SiDetectorElement.h"
 #include "InDetRecToolInterfaces/IInDetTestPixelLayerTool.h"
 #include "TrkVolumes/Volume.h"
 #include "TrkVolumes/CylinderVolumeBounds.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
 #include <set>
 
 //================ Constructor =================================================
@@ -38,21 +42,30 @@ InDet::InDetTrackHoleSearchTool::InDetTrackHoleSearchTool(const std::string& t,
   m_pixelCondSummarySvc("PixelConditionsSummarySvc",n),
   m_sctCondSummarySvc  ("SCT_ConditionsSummarySvc",n),
   m_pixelLayerTool("InDet::InDetTestPixelLayerTool"),
+  m_sctConfCondSvc("SCT_ConfigurationConditionsSvc", n),
+  m_sctBsErrSvc("SCT_ByteStreamErrorsSvc", n),
+  m_geoModelSvc("GeoModelSvc", n),
+  m_sct_id(nullptr),
   m_extendedListOfHoles(false),
   m_cosmic(false),
   m_usepix(true),
   m_usesct(true),
+  m_checkBadSCTChip(false),
   m_warning(0)
 {
   declareInterface<ITrackHoleSearchTool>(this);
   declareProperty("Extrapolator"         , m_extrapolator);
   declareProperty("PixelSummarySvc"      , m_pixelCondSummarySvc);
   declareProperty("SctSummarySvc"        , m_sctCondSummarySvc);
+  declareProperty("SctConfCondSvc"       , m_sctConfCondSvc);
+  declareProperty("SctBsErrSvc"          , m_sctBsErrSvc);
   declareProperty("PixelLayerTool"       , m_pixelLayerTool);
+  declareProperty("GeoModelService"      , m_geoModelSvc);
   declareProperty("ExtendedListOfHoles"  , m_extendedListOfHoles = false);
   declareProperty("Cosmics"              , m_cosmic);
   declareProperty("usePixel"             , m_usepix);
   declareProperty("useSCT"               , m_usesct);
+  declareProperty("checkBadSCTChip"      , m_checkBadSCTChip);
   declareProperty("minSiHits"            , m_minSiHits = 3);  
   declareProperty("CountDeadModulesAfterLastHit", m_countDeadModulesAfterLastHit = true);  
   declareProperty("phitol"               , m_phitol = 3.);
@@ -72,32 +85,32 @@ StatusCode InDet::InDetTrackHoleSearchTool::initialize()
 
   sc = detStore()->retrieve(m_atlasId, "AtlasID");
   if (sc.isFailure()) {
-    msg(MSG::ERROR) << "Could not get AtlasID helper !" << endreq;
+    ATH_MSG_ERROR("Could not get AtlasID helper !");
     return StatusCode::FAILURE;
   }
 
   // Get TrkExtrapolator from ToolService
   if ( m_extrapolator.retrieve().isFailure() ) {
-    msg(MSG::FATAL) << "Failed to retrieve tool " << m_extrapolator << endreq;
+    ATH_MSG_FATAL("Failed to retrieve tool " << m_extrapolator);
     return StatusCode::FAILURE;
   } else {
-    msg(MSG::INFO) << "Retrieved tool " << m_extrapolator << endreq;
+    ATH_MSG_INFO("Retrieved tool " << m_extrapolator);
   }
 
   if (m_usepix) {
     // Get PixelConditionsSummarySvc
     if ( m_pixelCondSummarySvc.retrieve().isFailure() ) {
-      msg(MSG::FATAL) << "Failed to retrieve tool " << m_pixelCondSummarySvc << endreq;
+      ATH_MSG_FATAL("Failed to retrieve tool " << m_pixelCondSummarySvc);
       return StatusCode::FAILURE;
     } else {
-      msg(MSG::INFO) << "Retrieved tool " << m_pixelCondSummarySvc << endreq;
+      ATH_MSG_INFO("Retrieved tool " << m_pixelCondSummarySvc);
     }
     // Get InDetPixelLayerTool from ToolService
     if ( m_pixelLayerTool.retrieve().isFailure() ) {
-      msg(MSG::FATAL) << "Failed to retrieve tool " << m_pixelLayerTool << endreq;
+      ATH_MSG_FATAL("Failed to retrieve tool " << m_pixelLayerTool);
       return StatusCode::FAILURE;
     } else {
-      msg(MSG::INFO) << "Retrieved tool " << m_pixelLayerTool << endreq;
+      ATH_MSG_INFO("Retrieved tool " << m_pixelLayerTool);
     }
 
   }
@@ -105,17 +118,51 @@ StatusCode InDet::InDetTrackHoleSearchTool::initialize()
   if (m_usesct) {
     // Get SctConditionsSummarySvc
     if ( m_sctCondSummarySvc.retrieve().isFailure() ) {
-      msg(MSG::FATAL) << "Failed to retrieve tool " << m_sctCondSummarySvc << endreq;
+      ATH_MSG_FATAL("Failed to retrieve service " << m_sctCondSummarySvc);
       return StatusCode::FAILURE;
     } else {
-      msg(MSG::INFO) << "Retrieved tool " << m_sctCondSummarySvc << endreq;
+      ATH_MSG_INFO("Retrieved service " << m_sctCondSummarySvc);
+    }
+
+    if(m_checkBadSCTChip) {
+      // Get SctConditionsSummarySvc
+      if ( m_sctConfCondSvc.retrieve().isFailure() ) {
+	ATH_MSG_FATAL("Failed to retrieve service " << m_sctConfCondSvc);
+	return StatusCode::FAILURE;
+      } else {
+	ATH_MSG_INFO("Retrieved service " << m_sctConfCondSvc);
+      }
+      // Get SCT_ByteStreamErrorsSvc
+      if ( m_sctBsErrSvc.retrieve().isFailure() ) {
+	ATH_MSG_FATAL("Failed to retrieve service " << m_sctBsErrSvc);
+	return StatusCode::FAILURE;
+      } else {
+	ATH_MSG_INFO("Retrieved service " << m_sctBsErrSvc);
+      }
+      // Get SCT_ID helper
+      if( detStore()->retrieve(m_sct_id, "SCT_ID").isFailure() ) {
+	ATH_MSG_FATAL("Cannot retrieve SCT ID helper!");
+	return StatusCode::FAILURE;
+      }
+
+      // Check if ITk Strip is used because isBadSCTChip method is valid only for SCT.
+      if(m_geoModelSvc.retrieve().isFailure()) {
+	ATH_MSG_FATAL("Could not locate GeoModelSvc");
+	return StatusCode::FAILURE;
+      }
+      if(m_geoModelSvc->geoConfig()==GeoModel::GEO_RUN4 or
+	 m_geoModelSvc->geoConfig()==GeoModel::GEO_ITk) {
+	ATH_MSG_WARNING("Since ITk Strip is used, m_checkBadSCTChip is turned off.");
+	m_checkBadSCTChip = false;
+      }
     }
   }
 
-  if (m_extendedListOfHoles) 
-    msg(MSG::INFO) << "Search for extended list of holes " << endreq;
+  if (m_extendedListOfHoles) {
+    ATH_MSG_INFO("Search for extended list of holes ");
+  }
 
-  msg(MSG::INFO) << "initialize() successful in " << name() << endreq;
+  ATH_MSG_INFO("initialize() successful in " << name());
   return StatusCode::SUCCESS;
 }
 
@@ -284,9 +331,9 @@ bool InDet::InDetTrackHoleSearchTool::getMapOfHits(const Trk::Track& track ,
                 ++imeas;
                 if (!(*iterTSOS)->trackParameters() && m_warning<10) {
                   m_warning++;
-                  msg(MSG::WARNING) << "No track parameters available for state of type measurement" << endreq;
-                  msg(MSG::WARNING) << "Don't run this tool on slimmed tracks!" << endreq;
-                  if (m_warning==10) msg(MSG::WARNING) << "(last message!)" << endreq;
+                  ATH_MSG_WARNING("No track parameters available for state of type measurement");
+                  ATH_MSG_WARNING("Don't run this tool on slimmed tracks!");
+                  if (m_warning==10) ATH_MSG_WARNING("(last message!)");
                 }
               }
 	      // for cosmics: remember parameters of first SI TSOS
@@ -524,20 +571,20 @@ bool InDet::InDetTrackHoleSearchTool::getMapOfHits(const Trk::Track& track ,
 		    {
 		      if (!foundFirst && !(*iterTSOS)->type(Trk::TrackStateOnSurface::Outlier))
 			{
-                          if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Found first Si measurement !" << endreq;
+                          ATH_MSG_VERBOSE("Found first Si measurement !");
 			  foundFirst = true;
 			}
 		      
 		      // is this a surface which might have a better prediction ?
 		      if (iTSOS->second->trackParameters())
 			{
-                          if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Found track parameter on Si surface, take it" << endreq;
+                          ATH_MSG_VERBOSE("Found track parameter on Si surface, take it");
 			  delete startParameters;
 			  startParameters = iTSOS->second->trackParameters()->clone();
 			}
 		      else
 			{
-                          if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "No parameter, take extrapolation" << endreq;
+                          ATH_MSG_VERBOSE("No parameter, take extrapolation");
 			  delete startParameters;
 			  startParameters = thisParameters->clone();
 			}
@@ -547,10 +594,10 @@ bool InDet::InDetTrackHoleSearchTool::getMapOfHits(const Trk::Track& track ,
 		  const Trk::TrackParameters *clonepar=thisParameters->clone();
 		  std::pair<const Trk::TrackParameters*,const bool> trackparampair (clonepar,true);
  		  if (mapOfPredictions.insert(std::pair<const Identifier, std::pair<const Trk::TrackParameters*,const bool> >(id2,trackparampair)).second){
-		     if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Added Si surface to mapOfPredictions" << endreq;
+		    ATH_MSG_VERBOSE("Added Si surface to mapOfPredictions");
 		  } 
 		  else {
-		     if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Had this, it is a double, skipped" << endreq;
+		    ATH_MSG_VERBOSE("Had this, it is a double, skipped");
 		    delete clonepar;
 		  }
 		}
@@ -565,7 +612,7 @@ bool InDet::InDetTrackHoleSearchTool::getMapOfHits(const Trk::Track& track ,
 	      
 	      if ( !(m_atlasId->is_pixel(id) || m_atlasId->is_sct(id)) )
 		{
-		   if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Target was no longer an Si element, break loop" << endreq;
+		  ATH_MSG_VERBOSE("Target was no longer an Si element, break loop");
 		  break;
   		}
 	      
@@ -799,7 +846,7 @@ void InDet::InDetTrackHoleSearchTool::performHoleSearchStepWise(std::map<const I
 	  else if (iter->second->type(Trk::TrackStateOnSurface::Measurement))
 	    ++imeasurements;
 	  else
-	    msg(MSG::ERROR) << "Found wrong TSOS in map !!!" << endreq;
+	    ATH_MSG_ERROR("Found wrong TSOS in map !!!");
 	}
 
       if ( imeasurements > 0 ) {
@@ -915,6 +962,13 @@ bool InDet::InDetTrackHoleSearchTool::isSensitive(const Trk::TrackParameters* pa
 	// this detElement is only cosidered as hole if the extrapolation of
 	// the track plus its error hits the active material
 	if (isActiveElement) {
+
+	  if(m_checkBadSCTChip and isBadSCTChip(id, *parameters, *siElement)) {
+	    ATH_MSG_VERBOSE ("Track is hiting a bad SCT chip, this is not a hole candidate!");
+	    isgood = false;
+	    return false;
+	  }
+
 	  ATH_MSG_VERBOSE ("SCT module is good, this is a hole candidate !");
 	  return true;
 	}
@@ -924,7 +978,7 @@ bool InDet::InDetTrackHoleSearchTool::isSensitive(const Trk::TrackParameters* pa
       }
     }
   } else {
-    msg(MSG::WARNING) << "unknown identifier type, this should not happen !" << endreq; 
+    ATH_MSG_WARNING("unknown identifier type, this should not happen !");
     return false;
   }
   // the extrapolation of the track plus its error might not 
@@ -987,7 +1041,7 @@ const Trk::Track*  InDet::InDetTrackHoleSearchTool::addHolesToTrack(const Trk::T
 	 DataVector doesn't have stable sort, so we need to tamper with
 	 its vector content in order to avoid sort to get caught in DV full
 	 object ownership */
-      if (msgLvl(MSG::DEBUG)) msg() << "sorting vector with stable_sort "<<endreq;
+      ATH_MSG_DEBUG("sorting vector with stable_sort ");
       std::vector<const Trk::TrackStateOnSurface*>* PtrVector
 	= const_cast<std::vector<const Trk::TrackStateOnSurface*>* > (&trackTSOS->stdcont());
       stable_sort( PtrVector->begin(), PtrVector->end(), *CompFunc );
@@ -1003,3 +1057,85 @@ const Trk::Track*  InDet::InDetTrackHoleSearchTool::addHolesToTrack(const Trk::T
   return newTrack;
 }
 
+// ====================================================================================================================
+bool InDet::InDetTrackHoleSearchTool::isBadSCTChip(const Identifier& waferId, 
+						   const Trk::TrackParameters& parameters,
+						   const InDetDD::SiDetectorElement& siElement) const {
+  // Check if the track passes through a bad SCT ABCD chip
+  // A chip is determined by the extrapolated position.
+  // Algorithm is based on InnerDetector/InDetMonitoring/SCT_Monitoring/src/SCTHitEffMonTool.cxx
+
+  // Check the input
+  if(not m_atlasId->is_sct(waferId)) {
+    ATH_MSG_WARNING(waferId << " is not an SCT Identifier");
+    return true;
+  }
+
+  // wafer id -> module id
+  const Identifier moduleId(m_sct_id->module_id(waferId));
+  // badChips word for the module from SCT_ConfigurationConditionsSvc
+  // tempMaskedChips word for the module from SCT_ByteStreamErrorSvc should also be added.
+  // https://its.cern.ch/jira/browse/ATLASRECTS-4011
+  unsigned int badChips(m_sctConfCondSvc->badChips(moduleId));
+  // badChips holds 12 bits. 
+  // bit 0 (LSB) is chip 0 for side 0.
+  // bit 5 is chip 5 for side 0.
+  // bit 6 is chip 6 for side 1.
+  // bit 11 is chip 11 for side 1.
+  // Temporarily masked chip information from SCT_ByteStreamErrorsSvc
+  const unsigned int tempMaskedChips(m_sctBsErrSvc->tempMaskedChips(moduleId));
+  // Information of chips with ABCD errors from SCT_ByteStreamErrorsSvc
+  const unsigned int abcdErrorChips(m_sctBsErrSvc->abcdErrorChips(moduleId));
+  // Take 'OR' of badChips, tempMaskedChips and abcdErrorChips
+  badChips |= tempMaskedChips;
+  badChips |= abcdErrorChips;
+
+  // If there is no bad chip, this check is done.
+  if(badChips==0) return false;
+
+  const int side(m_sct_id->side(waferId));
+  // Check the six chips on the side
+  // 0x3F  = 0000 0011 1111
+  // 0xFC0 = 1111 1100 0000
+  // If there is no bad chip on the side, this check is done.
+  if((side==0 and (badChips & 0x3F)==0) or (side==1 and (badChips & 0xFC0)==0)) return false;
+  
+  // There is at least one bad chip on the side.
+  // Get strip id from local position
+  const Amg::Vector2D localPos(parameters.localPosition());
+  const Identifier stripIdentifier(siElement.identifierOfPosition(localPos));
+  if(not m_atlasId->is_sct(stripIdentifier)) {
+    ATH_MSG_WARNING(stripIdentifier << " is not an SCT Identifier");
+    return true;
+  }
+  
+  // Get strip number from strip id
+  const int strip(m_sct_id->strip(stripIdentifier));
+  if(strip<0 or strip>=768) {
+    ATH_MSG_WARNING("strip number is invalid: " << strip);
+    return true;
+  }
+
+  // Conversion from strip to chip (specific for present SCT)
+  int chip(strip/128); // One ABCD chip reads 128 strips
+  // Relation between chip and offline strip is determined by the swapPhiReadoutDirection method.
+  // If swap is false
+  //  offline strip:   0            767
+  //  chip on side 0:  0  1  2  3  4  5
+  //  chip on side 1: 11 10  9  8  7  6
+  // If swap is true
+  //  offline strip:   0            767
+  //  chip on side 0:  5  4  3  2  1  0
+  //  chip on side 1:  6  7  8  9 10 11
+  const bool swap(siElement.swapPhiReadoutDirection());
+  if(side==0) {
+    chip = swap ?  5 - chip :     chip;
+  } else {
+    chip = swap ? 11 - chip : 6 + chip;
+  }
+  
+  // Check if the chip is bad
+  const bool badChip(badChips & (1<<chip));
+
+  return badChip;
+}