diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 8baddf032aa8c6c52b4a23dd69a0c4d1a1f71d3d..a114201fa81eb8cb02c74a3ebc93985f8f08374c 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -2516,6 +2516,22 @@ bool EncAppCfg::xCheckParameter()
   xConfirmPara( m_cbQpOffsetDualTree >  12,   "Max. Chroma Cb QP Offset for dual tree is  12" );
   xConfirmPara( m_crQpOffsetDualTree < -12,   "Min. Chroma Cr QP Offset for dual tree is -12" );
   xConfirmPara( m_crQpOffsetDualTree >  12,   "Max. Chroma Cr QP Offset for dual tree is  12" );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (m_dualTree && (m_chromaFormatIDC == CHROMA_400))
+  {
+    msg( WARNING, "****************************************************************************\n");
+    msg( WARNING, "** WARNING: --DualITree has been disabled because the chromaFormat is 400 **\n");
+    msg( WARNING, "****************************************************************************\n");
+    m_dualTree = false;
+  }
+  if (m_ccalf && (m_chromaFormatIDC == CHROMA_400))
+  {
+    msg( WARNING, "****************************************************************************\n");
+    msg( WARNING, "** WARNING: --CCALF has been disabled because the chromaFormat is 400     **\n");
+    msg( WARNING, "****************************************************************************\n");
+    m_ccalf = false;
+  }
+#endif
   if (m_JointCbCrMode && (m_chromaFormatIDC == CHROMA_400))
   {
     msg( WARNING, "****************************************************************************\n");
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index b9282a2e30d3d9393430d87f96d3e6e166b54300..b134d6cd30104f9943cbc93d60c4939c6542dbbd 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -964,7 +964,11 @@ void CodingStructure::createCoeffs(const bool isPLTused)
 
   if (isPLTused)
   {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    for (unsigned i = 0; i < (isChromaEnabled(area.chromaFormat) ? 2 : 1); i++)
+#else
     for (unsigned i = 0; i < numCh - 1; i++)
+#endif
     {
       unsigned _area = area.blocks[i].area();
 
diff --git a/source/Lib/CommonLib/Hash.cpp b/source/Lib/CommonLib/Hash.cpp
index 5657f3cb3fd66b4aa877f0a03eba16ac9afd4a32..9750be390676f5f808744f2cd963a684d33b28aa 100644
--- a/source/Lib/CommonLib/Hash.cpp
+++ b/source/Lib/CommonLib/Hash.cpp
@@ -377,9 +377,17 @@ void TComHash::getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, uns
 
   if (bitDepths.recon[CHANNEL_TYPE_LUMA] == 8 && bitDepths.recon[CHANNEL_TYPE_CHROMA] == 8)
   {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    Pel* curPel[MAX_NUM_COMPONENT]={nullptr};
+    int stride[MAX_NUM_COMPONENT]={0};
+    const int maxComponent=includeAllComponent?MAX_NUM_COMPONENT:1;
+
+    for (int id = 0; id < maxComponent; id++)
+#else
     Pel* curPel[3];
     int stride[3];
     for (int id = 0; id < 3; id++)
+#endif
     {
       ComponentID compID = ComponentID(id);
       stride[id] = (curPicBuf).get(compID).stride;
@@ -410,10 +418,19 @@ void TComHash::getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, uns
   else
   {
     int shift = bitDepths.recon[CHANNEL_TYPE_LUMA] - 8;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    int shiftc = includeAllComponent ? (bitDepths.recon[CHANNEL_TYPE_CHROMA] - 8) : 0;
+    Pel* curPel[MAX_NUM_COMPONENT]={nullptr};
+    int stride[MAX_NUM_COMPONENT]={0};
+    const int maxComponent=includeAllComponent?MAX_NUM_COMPONENT:1;
+
+    for (int id = 0; id < maxComponent; id++)
+#else
     int shiftc = bitDepths.recon[CHANNEL_TYPE_CHROMA] - 8;
     Pel* curPel[3];
     int stride[3];
     for (int id = 0; id < 3; id++)
+#endif
     {
       ComponentID compID = ComponentID(id);
       stride[id] = (curPicBuf).get(compID).stride;
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index ab4a35f8d3ab128b876e3de87312cc35b567260c..9b84b1a2a3e087ea00be1e857b725143e31f6826 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -1466,8 +1466,15 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB
     {
       if (bioApplied)
       {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        if (isChromaEnabled(yuvDstTmp->chromaFormat))
+        {
+#endif
         yuvDstTmp->bufs[1].copyFrom(pcYuvDst.bufs[1]);
         yuvDstTmp->bufs[2].copyFrom(pcYuvDst.bufs[2]);
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        }
+#endif
       }
       else
         yuvDstTmp->copyFrom(pcYuvDst, lumaOnly, chromaOnly);
@@ -1519,6 +1526,11 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu
   , PelUnitBuf* predBufWOBIO /*= NULL*/
 )
 {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  // Note: there appears to be an interaction with weighted prediction that
+  // makes the code follow different paths if chroma is on or off (in the encoder).
+  // Therefore for 4:0:0, "chroma" is not changed to false.
+#endif
   CHECK(predBufWOBIO && pu.ciipFlag, "the case should not happen!");
 
   if (!pu.cs->pcv->isEncoder)
@@ -1741,8 +1753,15 @@ void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitD
   else
   {
     m_if.weightedTriangleBlk( pu, pu.lumaSize().width,   pu.lumaSize().height,   COMPONENT_Y,  splitDir, predDst, predSrc0, predSrc1 );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (isChromaEnabled(pu.chromaFormat))
+    {
+#endif
     m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
     m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    }
+#endif
   }
 }
 #else
@@ -1760,7 +1779,7 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx
 
     geoMrgCtx.setMergeInfo( pu, candIdx0 );
     PU::spanMotionInfo( pu );
-    motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat));
+    motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); // TODO: check 4:0:0 interaction with weighted prediction.
     if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) )
     {
       printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() );
@@ -1768,7 +1787,7 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx
     
     geoMrgCtx.setMergeInfo( pu, candIdx1 );
     PU::spanMotionInfo( pu );
-    motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat));
+    motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); // TODO: check 4:0:0 interaction with weighted prediction.
     if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) )
     {
       printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() );
@@ -1791,8 +1810,15 @@ void InterPrediction::weightedGeoBlk( PredictionUnit &pu, const uint8_t splitDir
   else
   {
     m_if.weightedGeoBlk( pu, pu.lumaSize().width,   pu.lumaSize().height,   COMPONENT_Y,  splitDir, predDst, predSrc0, predSrc1 );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (isChromaEnabled(pu.chromaFormat))
+    {
+#endif
     m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
     m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    }
+#endif
   }
 }
 #endif
@@ -1848,7 +1874,11 @@ void InterPrediction::xPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList ref
   int offset = 0, width, height;
   int padsize;
   Mv cMv;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  for (int compID = 0; compID < getNumberValidComponents(pu.chromaFormat); compID++)
+#else
   for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+#endif
   {
     int filtersize = (compID == (COMPONENT_Y)) ? NTAPS_LUMA : NTAPS_CHROMA;
     width = pcPad.bufs[compID].width;
@@ -2011,7 +2041,11 @@ void InterPrediction::xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYu
         pu.lx(), pu.ly(), pu.lwidth(), pu.lheight(), startMv.getHor(), startMv.getVer(), tileArea.topLeft().x, tileArea.topLeft().y, tileArea.bottomRight().x, tileArea.bottomRight().y );
       THROW( "MCTS constraint failed!" );
     }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    for (int compID = 0; compID < getNumberValidComponents(pu.chromaFormat); compID++)
+#else
     for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
+#endif
     {
       Pel *srcBufPelPtr = NULL;
       int pcPadstride = 0;
@@ -2294,13 +2328,26 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con
         if (pu.mvdL0SubPu[num] != Mv(0, 0))
         {
           blockMoved = true;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+          if (isChromaEnabled(pu.chromaFormat))
+          {
+#endif
           xPrefetch(subPu, m_cYuvRefBuffDMVRL0, REF_PIC_LIST_0, 0);
           xPrefetch(subPu, m_cYuvRefBuffDMVRL1, REF_PIC_LIST_1, 0);
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+          }
+#endif
           xPad(subPu, m_cYuvRefBuffDMVRL0, REF_PIC_LIST_0);
           xPad(subPu, m_cYuvRefBuffDMVRL1, REF_PIC_LIST_1);
         }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        int dstStride[MAX_NUM_COMPONENT] = { pcYuvDst.bufs[COMPONENT_Y].stride,
+                                             isChromaEnabled(pu.chromaFormat) ? pcYuvDst.bufs[COMPONENT_Cb].stride : 0,
+                                             isChromaEnabled(pu.chromaFormat) ? pcYuvDst.bufs[COMPONENT_Cr].stride : 0};
+#else
         int dstStride[MAX_NUM_COMPONENT] = { pcYuvDst.bufs[COMPONENT_Y].stride, pcYuvDst.bufs[COMPONENT_Cb].stride, pcYuvDst.bufs[COMPONENT_Cr].stride };
+#endif
         subPu.mv[0] = mergeMv[REF_PIC_LIST_0] + pu.mvdL0SubPu[num];
         subPu.mv[1] = mergeMv[REF_PIC_LIST_1] - pu.mvdL0SubPu[num];
 
@@ -2313,10 +2360,16 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con
 
         subPredBuf.bufs[COMPONENT_Y].buf = pcYuvDst.bufs[COMPONENT_Y].buf + xStart + yStart * dstStride[COMPONENT_Y];
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        if (isChromaEnabled(pu.chromaFormat))
+        {
+#endif
         subPredBuf.bufs[COMPONENT_Cb].buf = pcYuvDst.bufs[COMPONENT_Cb].buf + (xStart >> scaleX) + ((yStart >> scaleY) * dstStride[COMPONENT_Cb]);
 
         subPredBuf.bufs[COMPONENT_Cr].buf = pcYuvDst.bufs[COMPONENT_Cr].buf + (xStart >> scaleX) + ((yStart >> scaleY) * dstStride[COMPONENT_Cr]);
-
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        }
+#endif
         xWeightedAverage(subPu, srcPred0, srcPred1, subPredBuf, subPu.cu->slice->getSPS()->getBitDepths(), subPu.cu->slice->clpRngs(), bioAppliedType[num]);
         num++;
       }
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 776a332baf4939a5722c71e5efe3c0106067c374..01e5cbcd60b672360c3a0523ae8b75058e896a8b 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -743,6 +743,12 @@ void IntraPrediction::geneIntrainterPred(const CodingUnit &cu)
 
   initIntraPatternChType(cu, pu->Y());
   predIntraAng(COMPONENT_Y, cu.cs->getPredBuf(*pu).Y(), *pu);
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  int maxCompID = 1;
+  if (isChromaEnabled(pu->chromaFormat))
+  {
+    maxCompID = MAX_NUM_COMPONENT;
+#endif
   if (pu->chromaSize().width > 2)
   {
     initIntraPatternChType(cu, pu->Cb());
@@ -751,10 +757,20 @@ void IntraPrediction::geneIntrainterPred(const CodingUnit &cu)
     initIntraPatternChType(cu, pu->Cr());
     predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+  for (int currCompID = 0; currCompID < maxCompID; currCompID++)
+  {
+    if (currCompID > 0 && pu->chromaSize().width <= 2)
+    {
+      continue;
+    }
+#else
   for (int currCompID = 0; currCompID < 3; currCompID++)
   {
     if (pu->chromaSize().width <= 2 && currCompID > 0)
       continue;
+#endif
     ComponentID currCompID2 = (ComponentID)currCompID;
     PelBuf tmpBuf = currCompID == 0 ? cu.cs->getPredBuf(*pu).Y() : (currCompID == 1 ? cu.cs->getPredBuf(*pu).Cb() : cu.cs->getPredBuf(*pu).Cr());
     switchBuffer(*pu, currCompID2, tmpBuf, getPredictorPtr2(currCompID2, 0));
diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp
index e0d8d547b1f000c7fd40b3b54bc3d7ae699f7ee7..a9e3a60c8eda3283e83e2dd86452e9a5f6d4c174 100644
--- a/source/Lib/CommonLib/LoopFilter.cpp
+++ b/source/Lib/CommonLib/LoopFilter.cpp
@@ -397,7 +397,12 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir )
     {
       xEdgeFilterLuma( cu, edgeDir, edge );
     }
+
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if ( pcv.chrFormat != CHROMA_400 && cu.blocks[COMPONENT_Cb].valid() )
+#else
     if ( cu.blocks[COMPONENT_Cb].valid() && pcv.chrFormat != CHROMA_400 )
+#endif
     {
       if ( !cu.ispMode || edge == 0 )
       {
@@ -457,7 +462,11 @@ void LoopFilter::xSetMaxFilterLengthPQFromTransformSizes( const DeblockEdgeDir e
 
   if ( edgeDir == EDGE_HOR )
   {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    for ( int cIdx = 0; cIdx < ::getNumberValidComponents(tuQ.chromaFormat); cIdx++ ) // per component
+#else
     for ( int cIdx = 0; cIdx < MAX_NUM_COMPONENT; cIdx++ ) // per component
+#endif
     {
       const ComponentID comp = ComponentID(cIdx);
       const ChannelType ch   = toChannelType(comp);
@@ -502,7 +511,11 @@ void LoopFilter::xSetMaxFilterLengthPQFromTransformSizes( const DeblockEdgeDir e
   }
   if ( edgeDir == EDGE_VER )
   {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    for ( int cIdx = 0; cIdx < ::getNumberValidComponents(tuQ.chromaFormat); cIdx++ ) // per component
+#else
     for ( int cIdx = 0; cIdx < MAX_NUM_COMPONENT; cIdx++ ) // per component
+#endif
     {
       const ComponentID comp = ComponentID(cIdx);
       const ChannelType ch   = toChannelType(comp);
@@ -710,6 +723,10 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De
   {
     tmpBs += BsSet(1, COMPONENT_Y);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (pcv.chrFormat != CHROMA_400)
+  {
+#endif
   // U
   if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Cb) || TU::getCbf(tuP, COMPONENT_Cb) || tuQ.jointCbCr || tuP.jointCbCr))
   {
@@ -720,6 +737,9 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De
   {
     tmpBs += BsSet(1, COMPONENT_Cr);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+#endif
   if (BsGet(tmpBs, COMPONENT_Y) == 1)
   {
     return tmpBs;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 756850b86b059df6a67a94fd810dd00696bd4a68..7ad29c25d90c25146497705b0cc3ae9f8aff16dc 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_Q0438_MONOCHROME_BUGFIXES                    1 // JVET-Q0438: Monochrome bug fixes
+
 #define JVET_Q0110_Q0785_CHROMA_BDPCM_420                 1 // JVET-Q0110/Q0785: Enable chroma BDPCM for 420, separate contexts for chroma BDPCM and bug-fixes.
 
 #define JVET_Q0512_ENC_CHROMA_TS_ACT                      1 // JVET-Q0512: encoder-side improvement on enabling chroma transform-skip for ACT
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 8a6d7c8d6af9f7ffacf47eff65c8cbf0d2b1d45c..304090f103a7c4a56b8645b6e3307cb42defbe2a 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -782,7 +782,12 @@ void TransformUnit::init(TCoeff **coeffs, Pel **pcmbuf, bool **runType)
     m_pcmbuf[i] = pcmbuf[i];
   }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  // numBlocks is either 1 for 4:0:0, or 3 otherwise. It would perhaps be better to loop over getNumberValidChannels(*cs->pcv.chrFormat) for m_runType.
+  for (uint32_t i = 0; i < std::max<uint32_t>(2, numBlocks)-1; i++)
+#else
   for (uint32_t i = 0; i < numBlocks - 1; i++)
+#endif
   {
     m_runType[i] = runType[i];
   }
diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp
index 71b35c0b274b80d1913d2f3705fb67d415048ae5..65803b7063ac660785fe203b667e3df49efbf825 100644
--- a/source/Lib/CommonLib/UnitPartitioner.cpp
+++ b/source/Lib/CommonLib/UnitPartitioner.cpp
@@ -253,7 +253,11 @@ void QTBTPartitioner::initCtu( const UnitArea& ctuArea, const ChannelType _chTyp
   currQtDepth = 0;
   currSubdiv  = 0;
   currQgPos   = ctuArea.lumaPos();
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  currQgChromaPos = ctuArea.chromaFormat != CHROMA_400 ? ctuArea.chromaPos() : Position();
+#else
   currQgChromaPos = ctuArea.chromaPos();
+#endif
   currImplicitBtDepth = 0;
   chType      = _chType;
 
@@ -374,7 +378,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
 
   // the minimal and maximal sizes are given in luma samples
   const CompArea&  area  = currArea().Y();
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  const CompArea  *areaC = (chType == CHANNEL_TYPE_CHROMA) ? &(currArea().Cb()) : nullptr;
+#else
   const CompArea&  areaC = currArea().Cb();
+#endif
         PartLevel& level = m_partStack.back();
 
   const PartSplit lastSplit = level.split;
@@ -383,7 +391,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   // don't allow QT-splitting below a BT split
   if( lastSplit != CTU_LEVEL && lastSplit != CU_QUAD_SPLIT ) canQt = false;
   if( area.width <= minQtSize )                              canQt = false;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if( areaC && areaC->width <= MIN_DUALTREE_CHROMA_WIDTH ) canQt = false;
+#else
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width <= MIN_DUALTREE_CHROMA_WIDTH ) canQt = false;
+#endif
   if( treeType == TREE_C )
   {
     canQt = canBh = canTh = canBv = canTv = false;
@@ -395,7 +407,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
 
     canBh = implicitSplit == CU_HORZ_SPLIT;
     canBv = implicitSplit == CU_VERT_SPLIT;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (areaC && areaC->width == 4) canBv = false;
+#else
     if (chType == CHANNEL_TYPE_CHROMA && areaC.width == 4) canBv = false;
+#endif
     return;
   }
 
@@ -431,20 +447,37 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca
   // specific check for BT splits
   if( area.height <= minBtSize )                            canBh = false;
   if( area.width > MAX_TB_SIZEY && area.height <= MAX_TB_SIZEY ) canBh = false;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE )     canBh = false;
+#else
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE )     canBh = false;
+#endif
   if( area.width <= minBtSize )                              canBv = false;
   if( area.width <= MAX_TB_SIZEY && area.height > MAX_TB_SIZEY ) canBv = false;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE || areaC->width == 4))     canBv = false;
+#else
   if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE || areaC.width == 4))     canBv = false;
+#endif
   if( modeType == MODE_TYPE_INTER && area.width * area.height == 32 )  canBv = canBh = false;
   if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize )
                                                                                        canTh = false;
   if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY )  canTh = false;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE*2 )     canTh = false;
+#else
   if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE*2 )     canTh = false;
+#endif
   if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize )
                                                                                        canTv = false;
   if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY )  canTv = false;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC->width == 8))     canTv = false;
+#else
   if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC.width == 8))     canTv = false;
+#endif
   if( modeType == MODE_TYPE_INTER && area.width * area.height == 64 )  canTv = canTh = false;
+
 }
 
 bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs )
@@ -570,7 +603,11 @@ void QTBTPartitioner::exitCurrSplit()
   currSubdiv--;
   if( currQgEnable() )
     currQgPos = currArea().lumaPos();
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if( currArea().chromaFormat != CHROMA_400 && currQgChromaEnable() )
+#else
   if( currQgChromaEnable() )
+#endif
     currQgChromaPos = currArea().chromaPos();
 #if _DEBUG
   m_currArea = m_partStack.back().parts[m_partStack.back().idx];
@@ -998,7 +1035,11 @@ void PartitionerImpl::getTUIntraSubPartitions( Partitioning &sub, const UnitArea
     THROW( "Unknown TU sub-partitioning" );
   }
   //we only partition luma, so there is going to be only one chroma tu at the end (unless it is dual tree, in which case there won't be any chroma components)
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  uint32_t partitionsWithoutChroma = (cs.area.chromaFormat == CHROMA_400) ? 0 : (isDualTree ? nPartitions : nPartitions - 1);
+#else
   uint32_t partitionsWithoutChroma = isDualTree ? nPartitions : nPartitions - 1;
+#endif
   for( uint32_t i = 0; i < partitionsWithoutChroma; i++ )
   {
     CompArea& blkCb = sub[i].blocks[COMPONENT_Cb];
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 9298a4cb2b9b42a1ba76a63a92f0dbf92e54d191..231476d8d3a07e1f7db7cf411c98844eaf8b5690 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -675,8 +675,13 @@ void DecCu::xReconInter(CodingUnit &cu)
 #endif
   CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together");
   const bool luma = cu.Y().valid();
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid();
+  if (luma && (chroma || !isChromaEnabled(cu.chromaFormat)))
+#else
   const bool chroma = cu.Cb().valid();
   if (luma && chroma)
+#endif
   {
     m_pcInterPred->motionCompensation(cu);
   }
@@ -698,7 +703,11 @@ void DecCu::xReconInter(CodingUnit &cu)
       cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT());
     }
     m_pcIntraPred->geneWeightedPred(COMPONENT_Y, cu.cs->getPredBuf(*cu.firstPU).Y(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Y, 0));
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (isChromaEnabled(cu.chromaFormat) && cu.chromaSize().width > 2)
+#else
     if (cu.chromaSize().width > 2)
+#endif
     {
       m_pcIntraPred->geneWeightedPred(COMPONENT_Cb, cu.cs->getPredBuf(*cu.firstPU).Cb(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cb, 0));
       m_pcIntraPred->geneWeightedPred(COMPONENT_Cr, cu.cs->getPredBuf(*cu.firstPU).Cr(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cr, 0));
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 5b851d934848790bc53284b1060affd058613456..1a366d48a6dcd2167a046e3a72e10a480fd57051 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -500,6 +500,10 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione
       partitioner.exitCurrSplit();
       if( chromaNotSplit )
       {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        if (isChromaEnabled(cs.pcv->chrFormat))
+        {
+#endif
         CHECK( partitioner.chType != CHANNEL_TYPE_LUMA, "must be luma status" );
         partitioner.chType = CHANNEL_TYPE_CHROMA;
         partitioner.treeType = TREE_C;
@@ -508,6 +512,9 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione
         {
           coding_tree( cs, partitioner, cuCtx );
         }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+        }
+#endif
 
         //recover
         partitioner.chType = CHANNEL_TYPE_LUMA;
@@ -693,7 +700,11 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C
   }
 #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420
   bdpcm_mode( cu, ComponentID( partitioner.chType ) );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (!CS::isDualITree(cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat))
+#else
   if (!CS::isDualITree(cs) && isLuma(partitioner.chType))
+#endif
       bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA));
 #endif
 
@@ -2485,12 +2496,21 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti
   const CodingUnit&       cu = *tu.cu;
   const UnitArea&         area = partitioner.currArea();
   const unsigned          trDepth = partitioner.currTrDepth;
+#if !JVET_Q0438_MONOCHROME_BUGFIXES
   const bool              chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode;
+#endif
   ChromaCbfs              chromaCbfs;
   CHECK(tu.depth != trDepth, " transform unit should be not be futher partitioned");
 
   // cbf_cb & cbf_cr
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (area.chromaFormat != CHROMA_400)
+  {
+    const bool              chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode;
+    if (area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
+#else
   if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP))
+#endif
   {
     {
       unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
@@ -2513,6 +2533,13 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti
   {
     chromaCbfs = ChromaCbfs(false);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+  else if (cu.isSepTree())
+  {
+    chromaCbfs = ChromaCbfs(false);
+  }
+#endif
 
   if (!isChroma(partitioner.chType))
   {
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index 252cea9d5bd56f04beaf784fb88c2f9b69846e29..c64f4eb330e7ae0f22863318c6daac38d143239a 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -1041,6 +1041,9 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda
             );
 
   // derive filter (chroma)
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (isChromaEnabled(cs.pcv->chrFormat))
+#endif
   {
     alfEncoder( cs, alfParam, orgYuv, recYuv, cs.getRecoBuf(), CHANNEL_TYPE_CHROMA
 #if ENABLE_QPA
@@ -2922,6 +2925,10 @@ void  EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar
   }
 
   //chroma
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (isChromaEnabled(cs.pcv->chrFormat))
+  {
+#endif
   m_alfParamTemp = alfParamNewFiltersBest;
   if( m_alfParamTemp.numAlternativesChroma < 1 )
   {
@@ -3129,6 +3136,9 @@ void  EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar
     }
     apss[cs.slice->getTileGroupApsIdChroma()] = m_apsMap->getPS((cs.slice->getTileGroupApsIdChroma() << NUM_APS_TYPE_LEN) + ALF_APS);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+#endif
 }
 
 void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitBuf& recExtBuf)
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 452e7cec6ccee5bf79c0e3bc78fe05b03f3e43d8..6cdfb0425431986081ed2848c516af27ecc9c3b4 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1512,6 +1512,10 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
     tempCS->picture->cs->getNumCuPuTuOffset( numCuPuTu );
     tempCS->picture->cs->useSubStructure( *tempCS, partitioner.chType, CS::getArea( *tempCS, partitioner.currArea(), partitioner.chType ), false, true, false, false );
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (isChromaEnabled(tempCS->pcv->chrFormat))
+    {
+#endif
     partitioner.chType = CHANNEL_TYPE_CHROMA;
     tempCS->treeType = partitioner.treeType = TREE_C;
 
@@ -1536,9 +1540,15 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
     tempCSChroma->releaseIntermediateData();
     bestCSChroma->releaseIntermediateData();
     //tempCS->picture->cs->releaseIntermediateData();
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+      m_CurrCtx--;
+    }
+#endif
     tempCS->picture->cs->clearCuPuTuIdxMap( partitioner.currArea(), numCuPuTu[0], numCuPuTu[1], numCuPuTu[2], numCuPuTu + 3 );
 
+#if !JVET_Q0438_MONOCHROME_BUGFIXES
     m_CurrCtx--;
+#endif
 
     //recover luma tree status
     partitioner.chType = CHANNEL_TYPE_LUMA;
@@ -1837,7 +1847,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS
           m_CABACEstimator->cu_pred_data   ( cu );
 #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420
           m_CABACEstimator->bdpcm_mode     ( cu, ComponentID(partitioner.chType) );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+          if (!CS::isDualITree(*cu.cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat))
+#else
           if (!CS::isDualITree(*cu.cs) && isLuma(partitioner.chType))
+#endif
               m_CABACEstimator->bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA));
 #endif
 
@@ -1862,7 +1876,15 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS
           // Check if low frequency non-separable transform (LFNST) is too expensive
           if( lfnstIdx && !cuCtx.lfnstLastScanPos && !cu.ispMode )
           {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+            bool cbfAtZeroDepth = cu.isSepTree() ?
+                                       cu.rootCbf
+                                     : (tempCS->area.chromaFormat != CHROMA_400 && std::min( cu.firstTU->blocks[ 1 ].width, cu.firstTU->blocks[ 1 ].height ) < 4) ?
+                                            TU::getCbfAtDepth( *cu.firstTU, COMPONENT_Y, 0 )
+                                          : cu.rootCbf;
+#else
             bool cbfAtZeroDepth = cu.isSepTree() ? cu.rootCbf : std::min( cu.firstTU->blocks[ 1 ].width, cu.firstTU->blocks[ 1 ].height ) < 4 ? TU::getCbfAtDepth( *cu.firstTU, COMPONENT_Y, 0 ) : cu.rootCbf;
+#endif
             if( cbfAtZeroDepth )
             {
               tempCS->cost = MAX_DOUBLE;
@@ -2626,7 +2648,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
 
       setMergeBestSATDCost( candCostList[0] );
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+      if (isIntrainterEnabled && isChromaEnabled(pu.cs->pcv->chrFormat))
+#else
       if (isIntrainterEnabled)
+#endif
       {
         pu.ciipFlag = true;
         for (uint32_t mergeCnt = 0; mergeCnt < uiNumMrgSATDCand; mergeCnt++)
@@ -2771,6 +2797,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             tmpBuf.rspSignal(m_pcReshape->getFwdLUT());
           }
           m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, bufIdx));
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+          if (isChromaEnabled(pu.chromaFormat))
+          {
+#endif
           if (pu.chromaSize().width > 2)
           {
           tmpBuf = tempCS->getPredBuf(pu).Cb();
@@ -2787,6 +2817,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
             tmpBuf = tempCS->getPredBuf(pu).Cr();
             tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cr());
           }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+          }
+#endif
         }
         else
         {
@@ -3001,6 +3034,10 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
     }
 
     // perform chroma weighting process
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (isChromaEnabled(pu.chromaFormat))
+    {
+#endif
     for( uint8_t i = 0; i < triangleNumMrgSATDCand; i++ )
     {
       uint8_t  mergeCand = triangleRdModeList[i];
@@ -3015,6 +3052,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
       pu.regularMergeFlag = false;
       m_pcInterSearch->weightedTriangleBlk( pu, splitDir, CHANNEL_TYPE_CHROMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
     }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    }
+#endif
 
     tempCS->initStructData( encTestMode.qp );
   }
diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp
index 27d5ae535f845188a40c21b020262bf7cf6d89ea..b697daf5fcf3dc91f90e6bfd8b518ff231dbf79d 100644
--- a/source/Lib/EncoderLib/EncReshape.cpp
+++ b/source/Lib/EncoderLib/EncReshape.cpp
@@ -366,6 +366,10 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats)
   }
 
   picY = pcPic->getOrigBuf(COMPONENT_Y);
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  double avgY = 0.0;
+  double varY = 0.0;
+#else
   PelBuf picU = pcPic->getOrigBuf(COMPONENT_Cb);
   PelBuf picV = pcPic->getOrigBuf(COMPONENT_Cr);
   const int widthC = picU.width;
@@ -373,6 +377,7 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats)
   const int strideC = picU.stride;
   double avgY = 0.0, avgU = 0.0, avgV = 0.0;
   double varY = 0.0, varU = 0.0, varV = 0.0;
+#endif
   for (int y = 0; y < height; y++)
   {
     for (int x = 0; x < width; x++)
@@ -382,6 +387,20 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats)
     }
     picY.buf += stride;
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  avgY = avgY / (width * height);
+  varY = varY / (width * height) - avgY * avgY;
+
+  if (isChromaEnabled(pcPic->chromaFormat))
+  {
+    PelBuf picU = pcPic->getOrigBuf(COMPONENT_Cb);
+    PelBuf picV = pcPic->getOrigBuf(COMPONENT_Cr);
+    const int widthC = picU.width;
+    const int heightC = picU.height;
+    const int strideC = picU.stride;
+    double avgU = 0.0, avgV = 0.0;
+    double varU = 0.0, varV = 0.0;
+#endif
   for (int y = 0; y < heightC; y++)
   {
     for (int x = 0; x < widthC; x++)
@@ -394,10 +413,14 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats)
     picU.buf += strideC;
     picV.buf += strideC;
   }
+#if !JVET_Q0438_MONOCHROME_BUGFIXES
   avgY = avgY / (width * height);
+#endif
   avgU = avgU / (widthC * heightC);
   avgV = avgV / (widthC * heightC);
+#if !JVET_Q0438_MONOCHROME_BUGFIXES
   varY = varY / (width * height) - avgY * avgY;
+#endif
   varU = varU / (widthC * heightC) - avgU * avgU;
   varV = varV / (widthC * heightC) - avgV * avgV;
   if (varY > 0)
@@ -405,6 +428,9 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats)
     stats.ratioStdU = sqrt(varU) / sqrt(varY);
     stats.ratioStdV = sqrt(varV) / sqrt(varY);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+#endif
 }
 void EncReshape::preAnalyzerLMCS(Picture *pcPic, const uint32_t signalType, const SliceType sliceType, const ReshapeCW& reshapeCW)
 {
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 5cb2192760e3cbd490b12f46305f48ab6c66c381..51ff99a7861f2842f10a4c8d09697415c6867e40 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -809,8 +809,15 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu,
 
 )
 {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if ( (!isChromaEnabled(pu.chromaFormat)) || (!pu.Cb().valid()) )
+  {
+    return 0;
+  }
+#else
   if (!pu.Cb().valid())
     return 0;
+#endif
 
   int bestCandIdx = 0;
   Distortion  sadBest = std::numeric_limits<Distortion>::max();
@@ -6934,7 +6941,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
       }
     }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if ( chroma && isChromaEnabled(tu.chromaFormat) && tu.blocks[COMPONENT_Cb].valid() )
+#else
     if ( chroma && tu.blocks[COMPONENT_Cb].valid() )
+#endif
     {
       const CompArea& cbArea = tu.blocks[COMPONENT_Cb];
       const CompArea& crArea = tu.blocks[COMPONENT_Cr];
@@ -7234,8 +7245,13 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
     m_CABACEstimator->resetBits();
     if( !tu.noResidual )
     {
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+      static const ComponentID cbf_getComp[MAX_NUM_COMPONENT] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y };
+      for( unsigned c = isChromaEnabled(tu.chromaFormat)?0 : 2; c < MAX_NUM_COMPONENT; c++)
+#else
     static const ComponentID cbf_getComp[3] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y };
     for( unsigned c = 0; c < numTBlocks; c++)
+#endif
     {
       const ComponentID compID = cbf_getComp[c];
       if (compID == COMPONENT_Y && !luma)
@@ -7495,7 +7511,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     else
     cs.getResiBuf().bufs[0].subtract(cs.getPredBuf().bufs[0]);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (chroma && isChromaEnabled(cs.pcv->chrFormat))
+#else
   if (chroma)
+#endif
   {
     cs.getResiBuf().bufs[1].copyFrom(cs.getOrgBuf().bufs[1]);
     cs.getResiBuf().bufs[2].copyFrom(cs.getOrgBuf().bufs[2]);
@@ -7626,7 +7646,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
   {
     cs.getOrgResiBuf().bufs[0].copyFrom(orgResidual.bufs[0]);
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (chroma && isChromaEnabled(cs.pcv->chrFormat))
+#else
   if (chroma)
+#endif
   {
     cs.getOrgResiBuf().bufs[1].copyFrom(orgResidual.bufs[1]);
     cs.getOrgResiBuf().bufs[2].copyFrom(orgResidual.bufs[2]);
@@ -7739,7 +7763,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     {
       cs.getResiBuf().bufs[0].fill(0); // Clear the residual image, if we didn't code it.
     }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (chroma && isChromaEnabled(cs.pcv->chrFormat))
+#else
     if (chroma)
+#endif
     {
       cs.getResiBuf().bufs[1].fill(0); // Clear the residual image, if we didn't code it.
       cs.getResiBuf().bufs[2].fill(0); // Clear the residual image, if we didn't code it.
@@ -7769,7 +7797,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
       }
     }
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (chroma && isChromaEnabled(cs.pcv->chrFormat))
+#else
   if (chroma)
+#endif
   {
     cs.getRecoBuf().bufs[1].reconstruct(cs.getPredBuf().bufs[1], cs.getResiBuf().bufs[1], cs.slice->clpRngs().comp[1]);
     cs.getRecoBuf().bufs[2].reconstruct(cs.getPredBuf().bufs[2], cs.getResiBuf().bufs[2], cs.slice->clpRngs().comp[2]);
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index ecacd5094dba4314d59e64e6713fbfb2108f82f6..e850c0f084290c4d0ce583d3589e79329869a4aa 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -2596,7 +2596,11 @@ void IntraSearch::xEncIntraHeader( CodingStructure &cs, Partitioner &partitioner
       }
 #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420
       m_CABACEstimator->bdpcm_mode  ( cu, ComponentID(partitioner.chType) );
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+      if (!CS::isDualITree(cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat))
+#else
       if (!CS::isDualITree(cs) && isLuma(partitioner.chType))
+#endif
           m_CABACEstimator->bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA));
 #endif
     }
@@ -2641,7 +2645,9 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner
 
   const bool subdiv        = currTU.depth > currDepth;
   ComponentID compID = partitioner.chType == CHANNEL_TYPE_LUMA ? COMPONENT_Y : COMPONENT_Cb;
+#if !JVET_Q0438_MONOCHROME_BUGFIXES
   const bool chromaCbfISP = currArea.blocks[COMPONENT_Cb].valid() && currCU.ispMode && !subdiv;
+#endif
 
   if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
   {
@@ -2652,7 +2658,14 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner
     CHECK( subdiv && !currCU.ispMode && isLuma( compID ), "No TU subdivision is allowed with QTBT" );
   }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  if (bChroma)
+  {
+    const bool chromaCbfISP = currArea.blocks[COMPONENT_Cb].valid() && currCU.ispMode && !subdiv;
+    if ( !currCU.ispMode || chromaCbfISP )
+#else
   if( bChroma && ( !currCU.ispMode || chromaCbfISP ) )
+#endif
   {
     const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat);
     const uint32_t cbfDepth = ( chromaCbfISP ? currDepth - 1 : currDepth );
@@ -2669,6 +2682,9 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner
       }
     }
   }
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  }
+#endif
 
   if (subdiv)
   {
@@ -3056,11 +3072,27 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
     m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cResScale*cResScale));
   }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+  PelBuf          crOrg;
+  PelBuf          crPred;
+  PelBuf          crResi;
+  PelBuf          crReco;
+
+  if (isChroma(compID))
+  {
+    const CompArea &crArea = tu.blocks[ COMPONENT_Cr ];
+    crOrg  = cs.getOrgBuf  ( crArea );
+    crPred = cs.getPredBuf ( crArea );
+    crResi = cs.getResiBuf ( crArea );
+    crReco = cs.getRecoBuf ( crArea );
+  }
+#else
   const CompArea &crArea = tu.blocks     [ COMPONENT_Cr ];
   PelBuf          crOrg  = cs.getOrgBuf  ( crArea );
   PelBuf          crPred = cs.getPredBuf ( crArea );
   PelBuf          crResi = cs.getResiBuf ( crArea );
   PelBuf          crReco = cs.getRecoBuf ( crArea );
+#endif
 
   if ( jointCbCr )
   {
diff --git a/source/Lib/Utilities/VideoIOYuv.cpp b/source/Lib/Utilities/VideoIOYuv.cpp
index 720d06212579459767a676b6174502cee7cb3caa..018b5574841ae914fb949becb870f004f3cdc080 100644
--- a/source/Lib/Utilities/VideoIOYuv.cpp
+++ b/source/Lib/Utilities/VideoIOYuv.cpp
@@ -915,7 +915,12 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp
     const bool b709Compliance=(bClipToRec709) && (m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8);     /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */
     const Pel minval = b709Compliance? ((   1 << (desired_bitdepth - 8))   ) : 0;
     const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1;
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    const bool processComponent = (size_t)compID < picOrg.bufs.size();
+    Pel* const dst = processComponent ? picOrg.get(compID).bufAt(0,0) : nullptr;
+#else
     Pel* const dst = picOrg.get(compID).bufAt(0,0);
+#endif
 #if EXTENSION_360_VIDEO
     const uint32_t stride444 = picOrg.get(compID).stride;
 #endif
@@ -924,6 +929,16 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp
       return false;
     }
 
+#if JVET_Q0438_MONOCHROME_BUGFIXES
+    if (processComponent)
+    {
+      if (! verifyPlane( dst, stride444, width444, height444, pad_h444, pad_v444, compID, format, m_fileBitdepth[chType]) )
+      {
+         EXIT("Source image contains values outside the specified bit range!");
+      }
+      scalePlane( picOrg.get(compID), m_bitdepthShift[chType], minval, maxval);
+    }
+#else
     if (! verifyPlane( dst, stride444, width444, height444, pad_h444, pad_v444, compID, format, m_fileBitdepth[chType]) )
     {
        EXIT("Source image contains values outside the specified bit range!");
@@ -933,6 +948,7 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp
     {
       scalePlane( picOrg.get(compID), m_bitdepthShift[chType], minval, maxval);
     }
+#endif
   }
 
 #if EXTENSION_360_VIDEO