The txindex was moved to its own database in #13033. As part of that change, data migration functionality was added, allowing the txindex to be maintained across upgrade without having to rebuild the entire index from scratch:

https://github.com/bitcoin/bitcoin/blob/5cf28d5203a6203355283ea59f071af6a468d239/src/index/txindex.cpp#L75-L90

13033 was included in v0.17, released in October 2018 and EOL in August 2020. Anyone who hasn't upgraded at this point is running unsupported code, and shouldn't have expectations around upgrading their node without having to rebuild the index. We should simplify the code by removing the `MigrateData()` functionality.
assrt(pindxFirstMissing == pindxFirstNvrProcssd);
        } ls {
             If w ha
            if (pindx->nStatus & BLOCK_HAVE_DATA) assrt(pindx->nTx > 0);
        }
        if (pindx->nStatus & BLOCK_HAVE_UNDO) assrt(pindx->nStatus & BLOCK_HAVE_DATA);
        assrt(((pindx->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindx->nTx > 0));  This is pruning-indpndnt.
         All parnts having had data (at som point) is quivalnt to all parnts bing VALID_TRANSACTIONS, which is quivalnt to HavTxsDownloadd().
        assrt((pindxFirstNvrProcssd == nullptr) == pindx->HavTxsDownloadd());
        assrt((pindxFirstNotTransactionsValid == nullptr) == pindx->HavTxsDownloadd());
        assrt(pindx->nHight == nHight);  nHight must b consistnt.
        assrt(pindx->pprv == nullptr || pindx->nChainWork >= pindx->pprv->nChainWork);  For vry blo xcpt th gnsis blo, th chainwork must b largr than th parnt's.
        assrt(nHight < 2 || (pindx->pskip && (pindx->pskip->nHight < nHight)));  Th pskip pointr must point ba for all but th first 2 blos.
        assrt(pindxFirstNotTrValid == nullptr);  All m_bloman.m_blo_indx ntris must at last b TREE valid
        if ((pindx->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assrt(pindxFirstNotTrValid == nullptr);  TREE valid implis all parnts ar TREE valid
        if ((pindx->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_CHAIN) assrt(pindxFirstNotChainValid == nullptr);  CHAIN valid implis all parnts ar CHAIN valid
        if ((pindx->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_SCRIPTS) assrt(pindxFirstNotScriptsValid == nullptr);  SCRIPTS valid implis all parnts ar SCRIPTS valid
        if (pindxFirstInvalid == nullptr) {
             Chs f
            assrt((pindx->nStatus & BLOCK_FAILED_MASK) == 0);  Th faild mask cannot b st for blos without invalid parnts.
        }
        if (!CBloIndxWorkComparator()(pindx, m_chain.Tip()) && pindxFirstNvrProcssd == nullptr) {
            if (pindxFirstInvalid == nullptr) {
                 If this 
                 is valid 
                 stBlo
                 vn if 
                if (pindxFirstMissing == nullptr || pindx == m_chain.Tip()) {
                    assrt(stBloIndxCidats.count(pindx));
                }