diff --git a/wallet/wallet.go b/wallet/wallet.go
index 33f9d72..efd12a5 100644
--- a/wallet/wallet.go
+++ b/wallet/wallet.go
@@ -2714,20 +2714,54 @@ func (w *Wallet) PublishTransaction(tx *wire.MsgTx) error {
 	// we'll write this tx to disk as an unconfirmed transaction. This way,
 	// upon restarts, we'll always rebroadcast it, and also add it to our
 	// set of records.
-	rec, err := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now())
+	txRec, err := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now())
 	if err != nil {
 		return err
 	}
 	err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
 		txmgrNs := tx.ReadWriteBucket(wtxmgrNamespaceKey)
-		return w.TxStore.InsertTx(txmgrNs, rec, nil)
+		return w.TxStore.InsertTx(txmgrNs, txRec, nil)
 	})
 	if err != nil {
 		return err
 	}
 
 	_, err = server.SendRawTransaction(tx, false)
-	return err
+	switch {
+	// The following are errors returned from btcd's mempool.
+	case strings.Contains(err.Error(), "spent"):
+		fallthrough
+	case strings.Contains(err.Error(), "orphan"):
+		fallthrough
+	case strings.Contains(err.Error(), "conflict"):
+		fallthrough
+
+	// The following errors are returned from bitcoind's mempool.
+	case strings.Contains(err.Error(), "fee not met"):
+		fallthrough
+	case strings.Contains(err.Error(), "Missing inputs"):
+		fallthrough
+	case strings.Contains(err.Error(), "already in block chain"):
+
+		// If the transaction was rejected, then we'll remove it from
+		// the txstore, as otherwise, we'll attempt to continually
+		// re-broadcast it, and the utxo state of the wallet won't be
+		// accurate.
+		dbErr := walletdb.Update(w.db, func(dbTx walletdb.ReadWriteTx) error {
+			txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey)
+
+			return w.TxStore.RemoveUnminedTx(txmgrNs, txRec)
+		})
+		if dbErr != nil {
+			return fmt.Errorf("unable to broadcast tx: %v, "+
+				"unable to remove invalid tx: %v", err, dbErr)
+		}
+
+		return err
+
+	default:
+		return err
+	}
 }
 
 // ChainParams returns the network parameters for the blockchain the wallet