diff --git a/indexedDb/impl/channels/implementation.go b/indexedDb/impl/channels/implementation.go
index dfc000eba4476870a38b3e6dbd7c8181f55fb5f3..8dc343afc0f093829535d98268d3f581a7fe1253 100644
--- a/indexedDb/impl/channels/implementation.go
+++ b/indexedDb/impl/channels/implementation.go
@@ -435,6 +435,26 @@ func (w *wasmModel) upsertMessage(msg *Message) (uint64, error) {
 	// Store message to database
 	msgIdObj, err := impl.Put(w.db, messageStoreName, messageObj)
 	if err != nil {
+		// Do not error out when this message already exists inside
+		// the DB. Instead, set the ID and re-attempt as an update.
+		if msg.ID == 0 { // always error out when not an insert attempt
+			msgID, inErr := message.UnmarshalID(msg.MessageID)
+			if inErr == nil {
+				jww.WARN.Printf("upsertMessage duplicate: %+v",
+					err)
+				rnd := &rounds.Round{ID: id.Round(msg.Round)}
+				status := (*channels.SentStatus)(&msg.Status)
+				return w.UpdateFromMessageID(msgID,
+					&msg.Timestamp,
+					rnd,
+					&msg.Pinned,
+					&msg.Hidden,
+					status)
+			}
+			// Add this to the main putMessage error
+			err = errors.Wrapf(err, "bad msg ID: %+v",
+				inErr)
+		}
 		return 0, errors.Errorf("Unable to put Message: %+v\n%s",
 			err, newMessageJson)
 	}
diff --git a/indexedDb/impl/channels/implementation_test.go b/indexedDb/impl/channels/implementation_test.go
index 58cd04a1c6d346a02d0073ef33e9e5e292c8607e..b652931769ab0e1aac4c76f27c08e03135146213 100644
--- a/indexedDb/impl/channels/implementation_test.go
+++ b/indexedDb/impl/channels/implementation_test.go
@@ -413,13 +413,16 @@ func Test_wasmModel_DuplicateReceives(t *testing.T) {
 			}
 
 			// Store duplicate messages with same messageID
+			referenceID := uint64(0)
 			for i := 0; i < 10; i++ {
 				uuid = eventModel.ReceiveMessage(channelID, msgID, "test",
 					testString+fmt.Sprintf("%d", i), []byte{8, 6, 7, 5}, 0, 0,
 					netTime.Now(), time.Hour, rnd, 0, channels.Sent, false)
-				if uuid != 0 {
-					t.Fatalf("Expected UUID to be zero for duplicate receives")
+				if referenceID == 0 {
+					referenceID = uuid
 				}
+				require.Equal(t, referenceID, uuid,
+					"UUID must be identical for duplicate receives")
 			}
 		})
 	}
@@ -587,3 +590,68 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) {
 		})
 	}
 }
+
+func TestUpsertMessageDuplicates(t *testing.T) {
+	msgJSON := []byte(`{"pubkey":"4gFD38jRhf/aNDRzaguLJHHgTncs0pwvNiRvjTBOaXk=",
+                "dm_token":3173028031,
+		"nickname":"",
+		"message_id":"BTi+V2anHhrRAEcCMm6g2Bs9oKn7PhQzCzvM7x8Ml7A=",
+		"channel_id":"Gt1T8t1GcnQXijiOjX5yjiLt3F8tnPB9S70ntBx86h8D",
+		"parent_message_id":null,
+		"pinned":false,
+		"hidden":false,
+		"round":151369004,
+		"codeset_version":0,
+		"timestamp": "2023-06-06T19:39:27.281204113Z",
+		"lease_v2":"30000000000",
+		"status":2,
+		"type":1,
+		"text":"KzT25s76K9AEIv0HadhjULkU37dkCUp/8N9+5UkkA8pLEBK71P7KFMr2xii/enYr4jpQcayNm82WD4wisimkK2wtaKb0hJIELAxJHxHilF2qVcDYn7zmx2ZiYkerZGTlf7DkHPZrA+EJJIu9gZ4ApR8TNVf15GxPSDGKHV6iv7vEMrrdoi4JKOFTpNsUjjbDykc91ADmmRlh5LUR/lqyt7bEasyVY2Zo+UiZpJrUJII0fhhn0HLbfs6ekg1tkq+vbPap3vNoebLZag3nEnMk+JqNjVW93BFICSMFv8cYX9q0sSK6sgHtz0HX9b7xTEFVHlCb2Zv/ErOX2LiedsgM4aGpOvjGYQM9ludCutVJArfM/5ejupMpvVPimY69QdevqxMm6v7c8H3abLQf4iKNVoaTaRygYFYArTWWoKep7BDZhjhCd4XnILGLjq7oeBfb3enMUSmeYabIuQpjAfRXU6cZh4cVomhEbkF5kj/rAc3GLzWtN1XcE5PC8bTL3m6YVN6hMCd1S7dsnDQ4FJQoDoqYzmTLD7jtyQujS86JsPkkt7kAIi14VxHTNEAM07cN6rH4VifWWMgQo4djPJ+nnsW9zUnylT9KS1GGyeaUhGC7GmrJGd7DmfHrhdWb9iMboKyH7VTm5C6X71JW1AhmdFfjtIHmWfhbAFsrP2gwkb4e+F86urUmK5LTT6qhGklUsXsmMFjwiEUCBWLSOZLKfITkNOBGIuGGcMi8Jtvwo1f4DHQ6sm/Y8qaJFmesyVKpA3MAVNawqlZJSJXflUA/mpJprFxLm/J3mdnxkLrqQSeSCAxHgpEdH3jiSPNhmn6QaJOVT+wotm+8lAq7qWgBWfMmcVSgWdAfVwujeP71Uo1y24/Z4+jXulFz1hPfbfmHk6/Qz4JlSgHZIqgOS1FTsmXFvBUe4moHR/QFDEXnz2LroRIavt9gWZPE3z1FIcjwSmtUzvpE8gZud+dKVVrjm8YPseq+IJ/AwRRlkUR5D0vf1TwEm0yQ7E+EotFvibQ="
+	}`)
+
+	// Initial call
+	msg1 := &Message{}
+	err := json.Unmarshal(msgJSON, msg1)
+	require.NoError(t, err)
+	msg1.Status = 0
+
+	// Second call
+	msg2 := &Message{}
+	err = json.Unmarshal(msgJSON, msg2)
+	require.NoError(t, err)
+	msg2.Status = 1
+
+	// Final call
+	msg3 := &Message{}
+	err = json.Unmarshal(msgJSON, msg3)
+	require.NoError(t, err)
+	msg3.Status = 2
+
+	cipher, err := idbCrypto.NewCipher(
+		[]byte("testPass"), []byte("testSalt"), 128,
+		csprng.NewSystemRNG())
+	require.NoError(t, err)
+	testString := "test_duplicateUpsertMessage"
+	eventModel, err := newWASMModel(testString, cipher,
+		&dummyCbs{})
+	require.NoError(t, err)
+
+	uuid, err := eventModel.upsertMessage(msg1)
+	require.NoError(t, err)
+	require.NotEqual(t, uuid, 0)
+
+	uuid2, err := eventModel.upsertMessage(msg2)
+	require.NoError(t, err)
+	require.Equal(t, uuid, uuid2)
+
+	uuid3, err := eventModel.upsertMessage(msg3)
+	require.NoError(t, err)
+	require.Equal(t, uuid, uuid3)
+
+	msgID, err := message.UnmarshalID(msg1.MessageID)
+	require.NoError(t, err)
+
+	modelMsg, err := eventModel.GetMessage(msgID)
+	require.NoError(t, err)
+	require.Equal(t, channels.Delivered, modelMsg.Status)
+}