diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensions.kt
index 258e67bc1..998bd1e2b 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensions.kt
@@ -20,6 +20,20 @@ inline fun <T : Any?, R : Any?> DataState<T>.map(
     is DataState.NoNetwork -> DataState.NoNetwork(data?.let(transform))
 }
 
+/**
+ * Maps the data inside a [DataState] with the given [transform] regardless of the data's
+ * nullability.
+ */
+inline fun <T : Any?, R : Any?> DataState<T>.mapNullable(
+    transform: (T?) -> R,
+): DataState<R> = when (this) {
+    is DataState.Loaded -> DataState.Loaded(data = transform(data))
+    is DataState.Loading -> DataState.Loading
+    is DataState.Pending -> DataState.Pending(data = transform(data))
+    is DataState.Error -> DataState.Error(error = error, data = transform(data))
+    is DataState.NoNetwork -> DataState.NoNetwork(data = transform(data))
+}
+
 /**
  * Emits all values of a [DataState] [Flow] until it emits a [DataState.Loaded].
  */
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt
index 800010d3a..772844ac6 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/vault/repository/VaultRepositoryImpl.kt
@@ -33,6 +33,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.DataState
 import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
 import com.x8bit.bitwarden.data.platform.repository.util.combineDataStates
 import com.x8bit.bitwarden.data.platform.repository.util.map
+import com.x8bit.bitwarden.data.platform.repository.util.mapNullable
 import com.x8bit.bitwarden.data.platform.repository.util.observeWhenSubscribedAndLoggedIn
 import com.x8bit.bitwarden.data.platform.repository.util.updateToPendingOrLoading
 import com.x8bit.bitwarden.data.platform.util.asFailure
@@ -508,11 +509,11 @@ class VaultRepositoryImpl(
                         combineDataStates(
                             totpCodeDataState,
                             cipherDataState,
-                        ) { totpCodeData, _ ->
-                            // Just return the verification items; we are only combining the
-                            // DataStates to know the overall state.
-                            totpCodeData
+                        ) { _, _ ->
+                            // We are only combining the DataStates to know the overall state,
+                            // we map it to the appropriate value below.
                         }
+                            .mapNullable { totpCodeDataState.data }
                     }
             }
             .stateIn(
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt
index 4936be5af..6a2db3d76 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt
@@ -13,6 +13,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
 import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
 import com.x8bit.bitwarden.data.platform.repository.model.DataState
 import com.x8bit.bitwarden.data.platform.repository.util.combineDataStates
+import com.x8bit.bitwarden.data.platform.repository.util.mapNullable
 import com.x8bit.bitwarden.data.vault.manager.FileManager
 import com.x8bit.bitwarden.data.vault.repository.VaultRepository
 import com.x8bit.bitwarden.data.vault.repository.model.DeleteCipherResult
@@ -89,12 +90,16 @@ class VaultItemViewModel @Inject constructor(
                 vaultDataState = combineDataStates(
                     cipherViewState,
                     authCodeState,
-                ) { vaultData, _ ->
-                    VaultItemStateData(
-                        cipher = vaultData,
-                        totpCodeItemData = totpCodeData,
-                    )
-                },
+                ) { _, _ ->
+                    // We are only combining the DataStates to know the overall state,
+                    // we map it to the appropriate value below.
+                }
+                    .mapNullable {
+                        VaultItemStateData(
+                            cipher = cipherViewState.data,
+                            totpCodeItemData = totpCodeData,
+                        )
+                    },
             )
         }
             .onEach(::sendAction)
@@ -743,8 +748,10 @@ class VaultItemViewModel @Inject constructor(
             is DataState.Error -> {
                 mutableStateFlow.update {
                     it.copy(
-                        viewState = VaultItemState.ViewState.Error(
-                            message = R.string.generic_error_message.asText(),
+                        viewState = vaultDataState.toViewStateOrError(
+                            isPremiumUser = userState.activeAccount.isPremium,
+                            totpCodeItemData = vaultDataState.data?.totpCodeItemData,
+                            errorText = R.string.generic_error_message.asText(),
                         ),
                     )
                 }
@@ -753,16 +760,11 @@ class VaultItemViewModel @Inject constructor(
             is DataState.Loaded -> {
                 mutableStateFlow.update {
                     it.copy(
-                        viewState = vaultDataState
-                            .data
-                            .cipher
-                            ?.toViewState(
-                                isPremiumUser = userState.activeAccount.isPremium,
-                                totpCodeItemData = vaultDataState.data.totpCodeItemData,
-                            )
-                            ?: VaultItemState.ViewState.Error(
-                                message = R.string.generic_error_message.asText(),
-                            ),
+                        viewState = vaultDataState.toViewStateOrError(
+                            isPremiumUser = userState.activeAccount.isPremium,
+                            totpCodeItemData = vaultDataState.data.totpCodeItemData,
+                            errorText = R.string.generic_error_message.asText(),
+                        ),
                     )
                 }
             }
@@ -776,10 +778,15 @@ class VaultItemViewModel @Inject constructor(
             is DataState.NoNetwork -> {
                 mutableStateFlow.update {
                     it.copy(
-                        viewState = VaultItemState.ViewState.Error(
-                            message = R.string.internet_connection_required_title
+                        viewState = vaultDataState.toViewStateOrError(
+                            isPremiumUser = userState.activeAccount.isPremium,
+                            totpCodeItemData = vaultDataState.data?.totpCodeItemData,
+                            errorText = R.string.internet_connection_required_title
                                 .asText()
-                                .concat(R.string.internet_connection_required_message.asText()),
+                                .concat(
+                                    " ".asText(),
+                                    R.string.internet_connection_required_message.asText(),
+                                ),
                         ),
                     )
                 }
@@ -788,22 +795,27 @@ class VaultItemViewModel @Inject constructor(
             is DataState.Pending -> {
                 mutableStateFlow.update {
                     it.copy(
-                        viewState = vaultDataState
-                            .data
-                            .cipher
-                            ?.toViewState(
-                                isPremiumUser = userState.activeAccount.isPremium,
-                                totpCodeItemData = vaultDataState.data.totpCodeItemData,
-                            )
-                            ?: VaultItemState.ViewState.Error(
-                                message = R.string.generic_error_message.asText(),
-                            ),
+                        viewState = vaultDataState.toViewStateOrError(
+                            isPremiumUser = userState.activeAccount.isPremium,
+                            totpCodeItemData = vaultDataState.data.totpCodeItemData,
+                            errorText = R.string.generic_error_message.asText(),
+                        ),
                     )
                 }
             }
         }
     }
 
+    private fun DataState<VaultItemStateData>.toViewStateOrError(
+        isPremiumUser: Boolean,
+        totpCodeItemData: TotpCodeItemData?,
+        errorText: Text,
+    ): VaultItemState.ViewState = this
+        .data
+        ?.cipher
+        ?.toViewState(isPremiumUser = isPremiumUser, totpCodeItemData = totpCodeItemData)
+        ?: VaultItemState.ViewState.Error(message = errorText)
+
     private fun handleValidatePasswordReceive(
         action: VaultItemAction.Internal.ValidatePasswordReceive,
     ) {
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensionsTest.kt
index 0239fc12a..162f9aa7c 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/util/DataStateExtensionsTest.kt
@@ -9,6 +9,184 @@ import org.junit.jupiter.api.Test
 
 class DataStateExtensionsTest {
 
+    @Test
+    fun `map on Loaded should call transform and return appropriate value for Loaded`() {
+        val mapValue = 5
+        val expected = DataState.Loaded(mapValue)
+        val dataState = DataState.Loaded("Loaded")
+
+        val result = dataState.map {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `map on Loading should not call transform and return Loading`() {
+        val dataState = DataState.Loading
+
+        val result = dataState.map {
+            5
+        }
+
+        assertEquals(dataState, result)
+    }
+
+    @Test
+    fun `map on Pending should call transform and return Pending`() {
+        val mapValue = 5
+        val expected = DataState.Pending(mapValue)
+        val dataState = DataState.Pending("Pending")
+
+        val result = dataState.map {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `map on Error should not call transform with null data and return Error`() {
+        val error = Throwable()
+        val dataState = DataState.Error(error, null)
+
+        val result = dataState.map {
+            5
+        }
+
+        assertEquals(dataState, result)
+    }
+
+    @Test
+    fun `map on Error should call transform with nonnull data and return Error`() {
+        val error = Throwable()
+        val mapValue = 5
+        val expected = DataState.Error(error, mapValue)
+        val dataState = DataState.Error(error, "Error")
+
+        val result = dataState.map {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `map on NoNetwork should not call transform with null data and return NoNetwork`() {
+        val dataState = DataState.NoNetwork(null)
+
+        val result = dataState.map {
+            5
+        }
+
+        assertEquals(dataState, result)
+    }
+
+    @Test
+    fun `map on NoNetwork should call transform with nonnull data and return NoNetwork`() {
+        val mapValue = 5
+        val expected = DataState.NoNetwork(mapValue)
+        val dataState = DataState.NoNetwork("NoNetwork")
+
+        val result = dataState.map {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on Loaded should call transform and return appropriate value for Loaded`() {
+        val mapValue = 5
+        val expected = DataState.Loaded(mapValue)
+        val dataState = DataState.Loaded("Loaded")
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on Loading should not call transform and return Loading`() {
+        val dataState = DataState.Loading
+
+        val result = dataState.mapNullable {
+            5
+        }
+
+        assertEquals(dataState, result)
+    }
+
+    @Test
+    fun `mapNullable on Pending should call transform and return Pending`() {
+        val mapValue = 5
+        val expected = DataState.Pending(mapValue)
+        val dataState = DataState.Pending("Pending")
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on Error should call transform with null data and return Error`() {
+        val error = Throwable()
+        val mapValue = 5
+        val expected = DataState.Error(error, mapValue)
+        val dataState = DataState.Error(error, null)
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on Error should call transform with nonnull data and return Error`() {
+        val error = Throwable()
+        val mapValue = 5
+        val expected = DataState.Error(error, mapValue)
+        val dataState = DataState.Error(error, "Error")
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on NoNetwork should call transform with null data and return NoNetwork`() {
+        val mapValue = 5
+        val expected = DataState.NoNetwork(mapValue)
+        val dataState = DataState.NoNetwork(null)
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
+    @Test
+    fun `mapNullable on NoNetwork should call transform with nonnull data and return NoNetwork`() {
+        val mapValue = 5
+        val expected = DataState.NoNetwork(5)
+        val dataState = DataState.NoNetwork("NoNetwork")
+
+        val result = dataState.mapNullable {
+            mapValue
+        }
+
+        assertEquals(expected, result)
+    }
+
     @Test
     fun `takeUtilLoaded should complete after a Loaded state is emitted`() = runTest {
         val mutableStateFlow = MutableStateFlow<DataState<Unit>>(DataState.Loading)
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt
index 856e0831a..205d2d78f 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt
@@ -22,6 +22,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.DownloadAttachmentResult
 import com.x8bit.bitwarden.data.vault.repository.model.RestoreCipherResult
 import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
 import com.x8bit.bitwarden.ui.platform.base.util.asText
+import com.x8bit.bitwarden.ui.platform.base.util.concat
 import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData
 import com.x8bit.bitwarden.ui.vault.feature.item.util.createCommonContent
 import com.x8bit.bitwarden.ui.vault.feature.item.util.createLoginContent
@@ -1949,6 +1950,158 @@ class VaultItemViewModelTest : BaseViewModelTest() {
         }
     }
 
+    @Nested
+    inner class VaultItemFlow {
+        @BeforeEach
+        fun setup() {
+            mutableUserStateFlow.value = DEFAULT_USER_STATE
+            mutableAuthCodeItemFlow.value = DataState.Loaded(data = null)
+        }
+
+        @Test
+        fun `on VaultDataReceive with Loading should update the dialog state to loading`() {
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Loading
+
+            assertEquals(
+                DEFAULT_STATE.copy(viewState = VaultItemState.ViewState.Loading),
+                viewModel.stateFlow.value,
+            )
+        }
+
+        @Test
+        fun `on VaultDataReceive with Loaded and nonnull data should update the ViewState`() {
+            val viewState = mockk<VaultItemState.ViewState>()
+            val cipherView = mockk<CipherView> {
+                every {
+                    toViewState(isPremiumUser = true, totpCodeItemData = null)
+                } returns viewState
+            }
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Loaded(data = cipherView)
+
+            assertEquals(DEFAULT_STATE.copy(viewState = viewState), viewModel.stateFlow.value)
+        }
+
+        @Test
+        fun `on VaultDataReceive with Loaded and null data should update the ViewState to Error`() {
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Loaded(data = null)
+
+            assertEquals(
+                DEFAULT_STATE.copy(
+                    viewState = VaultItemState.ViewState.Error(
+                        message = R.string.generic_error_message.asText(),
+                    ),
+                ),
+                viewModel.stateFlow.value,
+            )
+        }
+
+        @Test
+        fun `on VaultDataReceive with Pending and nonnull data should update the ViewState`() {
+            val viewState = mockk<VaultItemState.ViewState>()
+            val cipherView = mockk<CipherView> {
+                every {
+                    toViewState(isPremiumUser = true, totpCodeItemData = null)
+                } returns viewState
+            }
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Pending(data = cipherView)
+
+            assertEquals(DEFAULT_STATE.copy(viewState = viewState), viewModel.stateFlow.value)
+        }
+
+        @Suppress("MaxLineLength")
+        @Test
+        fun `on VaultDataReceive with Pending and null data should update the ViewState to Error`() {
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Pending(data = null)
+
+            assertEquals(
+                DEFAULT_STATE.copy(
+                    viewState = VaultItemState.ViewState.Error(
+                        message = R.string.generic_error_message.asText(),
+                    ),
+                ),
+                viewModel.stateFlow.value,
+            )
+        }
+
+        @Test
+        fun `on VaultDataReceive with Error and nonnull data should update the ViewState`() {
+            val viewState = mockk<VaultItemState.ViewState>()
+            val cipherView = mockk<CipherView> {
+                every {
+                    toViewState(isPremiumUser = true, totpCodeItemData = null)
+                } returns viewState
+            }
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Error(error = Throwable(), data = cipherView)
+
+            assertEquals(DEFAULT_STATE.copy(viewState = viewState), viewModel.stateFlow.value)
+        }
+
+        @Test
+        fun `on VaultDataReceive with Error and null data should update the ViewState to Error`() {
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.Error(error = Throwable(), data = null)
+
+            assertEquals(
+                DEFAULT_STATE.copy(
+                    viewState = VaultItemState.ViewState.Error(
+                        message = R.string.generic_error_message.asText(),
+                    ),
+                ),
+                viewModel.stateFlow.value,
+            )
+        }
+
+        @Test
+        fun `on VaultDataReceive with NoNetwork and nonnull data should update the ViewState`() {
+            val viewState = mockk<VaultItemState.ViewState>()
+            val cipherView = mockk<CipherView> {
+                every {
+                    toViewState(isPremiumUser = true, totpCodeItemData = null)
+                } returns viewState
+            }
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.NoNetwork(data = cipherView)
+
+            assertEquals(DEFAULT_STATE.copy(viewState = viewState), viewModel.stateFlow.value)
+        }
+
+        @Suppress("MaxLineLength")
+        @Test
+        fun `on VaultDataReceive with NoNetwork and null data should update the ViewState to Error`() {
+            val viewModel = createViewModel(state = null)
+
+            mutableVaultItemFlow.value = DataState.NoNetwork(data = null)
+
+            assertEquals(
+                DEFAULT_STATE.copy(
+                    viewState = VaultItemState.ViewState.Error(
+                        message = R.string.internet_connection_required_title
+                            .asText()
+                            .concat(
+                                " ".asText(),
+                                R.string.internet_connection_required_message.asText(),
+                            ),
+                    ),
+                ),
+                viewModel.stateFlow.value,
+            )
+        }
+    }
+
     @Suppress("LongParameterList")
     private fun createViewModel(
         state: VaultItemState?,