Currently it is possible to stupidly lose mempool data by calling the rpc "savemempool" before the previous stored mempool has been read and processed to the memory mempool.

I haven't looked at the code yet, but at minimum one ugly solution would be to have a global g_is_mempool_read_finished (or something of the short) that starts false and gets sets to true once the reading is reading processing of mempool.dat is successfully finished. The rpc savemempool checks this global on the start and returns a an error while it remains false.

class CBlockTreeDB;
class CChainParams;
class CCoinsViewDB;
class CInv;
class CConnman;
class CScriptCheck;
class CBlockPolicyEstimator;
class CTxMemPool;
class CValidationState;
struct ChainTxData;
struct PrecomputedTransactionData;
struct LockPoints;
static const bool DEFAULT_WHITELISTRELAY = true;
static const bool DEFAULT_WHITELISTFORCERELAY = true;
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000;
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN;
static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB;
static const unsigned int DEFAULT_ANCESTOR_LIMIT = 25;
static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 101;
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25;
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101;
static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336;
static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000;
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; 
static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; 
static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; 
static const int MAX_SCRIPTCHECK_THREADS = 16;
static const int DEFAULT_SCRIPTCHECK_THREADS = 0;
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;