blockchain.info – Validation Error: Error #-26: 258: txn-mempool-conflict


This error means that you’re trying to spend the same transaction output more than once.

More specifically, when you submit a transaction, a check is done (on the node) against the previous outputs of your new transaction to see if they are already trying to be spent by a transaction in the memory pool.

The check is in validation.cpp in the bitcoin source:

// Check for conflicts with in-memory transactions
std::set<uint256> setConflicts;
for (const CTxIn &txin : tx.vin)
{
    auto itConflicting = pool.mapNextTx.find(txin.prevout);
    if (itConflicting != pool.mapNextTx.end())
    {
        const CTransaction *ptxConflicting = itConflicting->second;
        if (!setConflicts.count(ptxConflicting->GetHash()))
        {
            // Allow opt-out of transaction replacement by setting
            // nSequence > MAX_BIP125_RBF_SEQUENCE (SEQUENCE_FINAL-2) on all inputs.
            //
            // SEQUENCE_FINAL-1 is picked to still allow use of nLockTime by
            // non-replaceable transactions. All inputs rather than just one
            // is for the sake of multi-party protocols, where we don't
            // want a single party to be able to disable replacement.
            //
            // The opt-out ignores descendants as anyone relying on
            // first-seen mempool behavior should be checking all
            // unconfirmed ancestors anyway; doing otherwise is hopelessly
            // insecure.
            bool fReplacementOptOut = true;
            if (fEnableReplacement)
            {
                for (const CTxIn &_txin : ptxConflicting->vin)
                {
                    if (_txin.nSequence <= MAX_BIP125_RBF_SEQUENCE)
                    {
                        fReplacementOptOut = false;
                        break;
                    }
                }
            }
            if (fReplacementOptOut) {
                return state.Invalid(false, REJECT_DUPLICATE, "txn-mempool-conflict");
            }

            setConflicts.insert(ptxConflicting->GetHash());
        }
    }
}