diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..55b2acb7cdec3cf93d9a5984555c4fa8ff330afe
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/SubmissionTanInvalidException.kt
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Corona-Warn-App                                                            *
+ *                                                                            *
+ * SAP SE and all other contributors /                                        *
+ * copyright owners license this file to you under the Apache                 *
+ * License, Version 2.0 (the "License"); you may not use this                 *
+ * file except in compliance with the License.                                *
+ * You may obtain a copy of the License at                                    *
+ *                                                                            *
+ * http://www.apache.org/licenses/LICENSE-2.0                                 *
+ *                                                                            *
+ * Unless required by applicable law or agreed to in writing,                 *
+ * software distributed under the License is distributed on an                *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     *
+ * KIND, either express or implied.  See the License for the                  *
+ * specific language governing permissions and limitations                    *
+ * under the License.                                                         *
+ ******************************************************************************/
+
+package de.rki.coronawarnapp.exception
+
+/**
+ * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder]
+ *
+ * @param message an Exception thrown inside the WebRequestBuilder
+ * @param cause the cause of the error
+ */
+class SubmissionTanInvalidException(message: String, cause: Throwable) : Exception(message, cause)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b2af0b017dc78c66307862b0fb7486ab61ba77dc
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestAlreadyPairedException.kt
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Corona-Warn-App                                                            *
+ *                                                                            *
+ * SAP SE and all other contributors /                                        *
+ * copyright owners license this file to you under the Apache                 *
+ * License, Version 2.0 (the "License"); you may not use this                 *
+ * file except in compliance with the License.                                *
+ * You may obtain a copy of the License at                                    *
+ *                                                                            *
+ * http://www.apache.org/licenses/LICENSE-2.0                                 *
+ *                                                                            *
+ * Unless required by applicable law or agreed to in writing,                 *
+ * software distributed under the License is distributed on an                *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     *
+ * KIND, either express or implied.  See the License for the                  *
+ * specific language governing permissions and limitations                    *
+ * under the License.                                                         *
+ ******************************************************************************/
+
+package de.rki.coronawarnapp.exception
+
+/**
+ * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder]
+ *
+ * @param message an Exception thrown inside the WebRequestBuilder
+ * @param cause the cause of the error
+ */
+class TestAlreadyPairedException(message: String, cause: Throwable) : Exception(message, cause)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..77619440763a0013c56848bdeb4267ea0bda7f26
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/TestPairingInvalidException.kt
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * Corona-Warn-App                                                            *
+ *                                                                            *
+ * SAP SE and all other contributors /                                        *
+ * copyright owners license this file to you under the Apache                 *
+ * License, Version 2.0 (the "License"); you may not use this                 *
+ * file except in compliance with the License.                                *
+ * You may obtain a copy of the License at                                    *
+ *                                                                            *
+ * http://www.apache.org/licenses/LICENSE-2.0                                 *
+ *                                                                            *
+ * Unless required by applicable law or agreed to in writing,                 *
+ * software distributed under the License is distributed on an                *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                     *
+ * KIND, either express or implied.  See the License for the                  *
+ * specific language governing permissions and limitations                    *
+ * under the License.                                                         *
+ ******************************************************************************/
+
+package de.rki.coronawarnapp.exception
+
+/**
+ * An Exception thrown when an error occurs inside the [de.rki.coronawarnapp.http.WebRequestBuilder]
+ *
+ * @param message an Exception thrown inside the WebRequestBuilder
+ * @param cause the cause of the error
+ */
+class TestPairingInvalidException(message: String, cause: Throwable) : Exception(message, cause)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
index beef25125312cb51f5bde31a23a251ba8588ad63..f7a653b72680251ebde926dfa2add83cbc7a771e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
@@ -77,4 +77,6 @@ object DiagnosisKeyConstants {
 
     /** Available Dates URL built from CDN URL's and REST resources */
     val AVAILABLE_DATES_URL = "$DIAGNOSIS_KEYS_DOWNLOAD_URL/$COUNTRY/$CURRENT_COUNTRY/$DATE"
+
+    const val SERVER_ERROR_CODE_403 = 403
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
index 24682d27e24334a78c12e7e8438a41656be37b80..e30de86ea5638e506f54bbe7e1fa17af954907ae 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
@@ -23,7 +23,10 @@ import KeyExportFormat
 import android.util.Log
 import de.rki.coronawarnapp.exception.DiagnosisKeyRetrievalException
 import de.rki.coronawarnapp.exception.DiagnosisKeySubmissionException
+import de.rki.coronawarnapp.exception.SubmissionTanInvalidException
 import de.rki.coronawarnapp.http.WebRequestBuilder
+import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants.SERVER_ERROR_CODE_403
+import retrofit2.HttpException
 
 /**
  * The Diagnosis Key Service is used to interact with the Server to submit and retrieve keys through
@@ -54,8 +57,14 @@ object DiagnosisKeyService {
                 false,
                 keysToReport
             )
-        } catch (e: Exception) {
-            throw DiagnosisKeySubmissionException(e)
+        } catch (e: HttpException) {
+            if (e.code() == SERVER_ERROR_CODE_403) {
+                throw SubmissionTanInvalidException(
+                    "the test paring to the device is invalid",
+                    e
+                )
+            }
+            throw e
         }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
index a99128c90139e6e25660ee52dcda1740142288d6..4150a275b99715addd407de02bd75a9ce8801416 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
@@ -20,4 +20,6 @@ object SubmissionConstants {
     const val MAX_QR_CODE_LENGTH = 150
     const val MAX_GUID_LENGTH = 80
     const val GUID_SEPARATOR = '?'
+
+    const val SERVER_ERROR_CODE_400 = 400
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
index c50399d451d64d9d6df4c21c22525e09ef3cf362..efbbe6e5adb8c12eb209fada488c292634c0f44d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
@@ -2,24 +2,38 @@ package de.rki.coronawarnapp.service.submission
 
 import de.rki.coronawarnapp.exception.NoGUIDOrTANSetException
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
+import de.rki.coronawarnapp.exception.TestAlreadyPairedException
+import de.rki.coronawarnapp.exception.TestPairingInvalidException
 import de.rki.coronawarnapp.http.WebRequestBuilder
 import de.rki.coronawarnapp.service.submission.SubmissionConstants.QR_CODE_KEY_TYPE
+import de.rki.coronawarnapp.service.submission.SubmissionConstants.SERVER_ERROR_CODE_400
 import de.rki.coronawarnapp.service.submission.SubmissionConstants.TELE_TAN_KEY_TYPE
 import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction
 import de.rki.coronawarnapp.util.formatter.TestResult
+import retrofit2.HttpException
 
 object SubmissionService {
     suspend fun asyncRegisterDevice() {
-        val testGUID = LocalData.testGUID()
-        val testTAN = LocalData.teletan()
-
-        when {
-            testGUID != null -> asyncRegisterDeviceViaGUID(testGUID)
-            testTAN != null -> asyncRegisterDeviceViaTAN(testTAN)
-            else -> throw NoGUIDOrTANSetException()
+        try {
+            val testGUID = LocalData.testGUID()
+            val testTAN = LocalData.teletan()
+
+            when {
+                testGUID != null -> asyncRegisterDeviceViaGUID(testGUID)
+                testTAN != null -> asyncRegisterDeviceViaTAN(testTAN)
+                else -> throw NoGUIDOrTANSetException()
+            }
+            LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis())
+        } catch (err: HttpException) {
+            if (err.code() == SERVER_ERROR_CODE_400) {
+                throw TestAlreadyPairedException(
+                    "the test was already paired to a different device",
+                    err
+                )
+            }
+            throw err
         }
-        LocalData.devicePairingSuccessfulTimestamp(System.currentTimeMillis())
     }
 
     private suspend fun asyncRegisterDeviceViaGUID(guid: String) {
@@ -45,8 +59,17 @@ object SubmissionService {
     }
 
     suspend fun asyncRequestAuthCode(registrationToken: String): String {
-        val authCode = WebRequestBuilder.asyncGetTan(registrationToken)
-        return authCode
+        try {
+            return WebRequestBuilder.asyncGetTan(registrationToken)
+        } catch (err: HttpException) {
+            if (err.code() == SERVER_ERROR_CODE_400) {
+                throw TestPairingInvalidException(
+                    "the test paring to the device is invalid",
+                    err
+                )
+            }
+            throw err
+        }
     }
 
     suspend fun asyncSubmitExposureKeys() {
@@ -88,10 +111,6 @@ object SubmissionService {
         LocalData.devicePairingSuccessfulTimestamp(0L)
     }
 
-    private fun deleteAuthCode() {
-        LocalData.authCode(null)
-    }
-
     private fun deleteTeleTAN() {
         LocalData.teletan(null)
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt
index de5655f4a419e237b74ca1f6c6cdea45f6cad8cb..6a49eba8ca92c452b53d07b1110b19a20566f39d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionRegisterDeviceFragment.kt
@@ -6,9 +6,13 @@ import android.view.View
 import android.view.ViewGroup
 import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.Observer
+import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionRegisterDeviceBinding
+import de.rki.coronawarnapp.exception.TestAlreadyPairedException
 import de.rki.coronawarnapp.ui.BaseFragment
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
+import de.rki.coronawarnapp.util.DialogHelper
+import retrofit2.HttpException
 
 class SubmissionRegisterDeviceFragment : BaseFragment() {
     private val viewModel: SubmissionViewModel by activityViewModels()
@@ -30,6 +34,46 @@ class SubmissionRegisterDeviceFragment : BaseFragment() {
         _binding = null
     }
 
+    private fun navigateToDispatchScreen() = doNavigate(
+        SubmissionRegisterDeviceFragmentDirections
+            .actionSubmissionRegisterDeviceFragmentToSubmissionDispatcherFragment()
+    )
+
+    private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance {
+        return when (exception) {
+            is TestAlreadyPairedException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_test_paired_title,
+                R.string.submission_error_dialog_web_test_paired_body,
+                R.string.submission_error_dialog_web_test_paired_button_positive,
+                null,
+                true,
+                ::navigateToDispatchScreen
+            )
+            is HttpException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                getString(
+                    R.string.submission_error_dialog_web_generic_network_error_body,
+                    exception.code()
+                ),
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToDispatchScreen
+            )
+            else -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                R.string.submission_error_dialog_web_generic_error_body,
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToDispatchScreen
+            )
+        }
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
@@ -41,6 +85,12 @@ class SubmissionRegisterDeviceFragment : BaseFragment() {
                 )
             }
         })
+
+        viewModel.registrationError.observe(viewLifecycleOwner, Observer {
+            if (it != null) {
+                DialogHelper.showDialog(buildErrorDialog(it))
+            }
+        })
     }
 
     override fun onResume() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
index 7fc0b62982dad204ebd94c0cc3b84db311d32972..2322c093d30d091e4c13cca61a2faa745ccfdbca 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
@@ -9,11 +9,14 @@ import androidx.lifecycle.Observer
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionPositiveOtherWarningBinding
+import de.rki.coronawarnapp.exception.SubmissionTanInvalidException
+import de.rki.coronawarnapp.exception.TestPairingInvalidException
 import de.rki.coronawarnapp.nearby.InternalExposureNotificationPermissionHelper
 import de.rki.coronawarnapp.ui.BaseFragment
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
 import de.rki.coronawarnapp.util.DialogHelper
+import retrofit2.HttpException
 
 class SubmissionResultPositiveOtherWarningFragment : BaseFragment(),
     InternalExposureNotificationPermissionHelper.Callback {
@@ -66,10 +69,60 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(),
         _binding = null
     }
 
+    private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance {
+        return when (exception) {
+            is TestPairingInvalidException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_paring_invalid_title,
+                R.string.submission_error_dialog_web_paring_invalid_body,
+                R.string.submission_error_dialog_web_paring_invalid_button_positive,
+                null,
+                true,
+                ::navigateToSubmissionResultFragment
+            )
+            is SubmissionTanInvalidException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_tan_invalid_title,
+                R.string.submission_error_dialog_web_tan_invalid_body,
+                R.string.submission_error_dialog_web_tan_invalid_button_positive,
+                null,
+                true,
+                ::navigateToSubmissionResultFragment
+            )
+            is HttpException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                getString(
+                    R.string.submission_error_dialog_web_generic_network_error_body,
+                    exception.code()
+                ),
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToSubmissionResultFragment
+            )
+            else -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                R.string.submission_error_dialog_web_generic_error_body,
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToSubmissionResultFragment
+            )
+        }
+    }
+
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
         setButtonOnClickListener()
 
+        submissionViewModel.submissionError.observe(viewLifecycleOwner, Observer {
+            if (it != null) {
+                DialogHelper.showDialog(buildErrorDialog(it))
+            }
+        })
+
         submissionViewModel.submissionState.observe(viewLifecycleOwner, Observer {
             if (it == ApiRequestState.SUCCESS) {
                 doNavigate(
@@ -85,13 +138,16 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(),
             initiateWarningOthers()
         }
         binding.submissionPositiveOtherWarningHeader.headerButtonBack.buttonIcon.setOnClickListener {
-            doNavigate(
-                SubmissionResultPositiveOtherWarningFragmentDirections
-                    .actionSubmissionResultPositiveOtherWarningFragmentToSubmissionResultFragment()
-            )
+            navigateToSubmissionResultFragment()
         }
     }
 
+    private fun navigateToSubmissionResultFragment() =
+        doNavigate(
+            SubmissionResultPositiveOtherWarningFragmentDirections
+                .actionSubmissionResultPositiveOtherWarningFragmentToSubmissionResultFragment()
+        )
+
     private fun initiateWarningOthers() {
         if (tracingViewModel.isTracingEnabled.value != true) {
             val tracingRequiredDialog = DialogHelper.DialogInstance(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
index 553ce28b902a44cac9b0d6cbf27c9251de4b9862..737e8f6e38a1b7bcd29260d52a91378d8dab725a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
@@ -5,12 +5,14 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultBinding
 import de.rki.coronawarnapp.ui.BaseFragment
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
 import de.rki.coronawarnapp.util.DialogHelper
+import retrofit2.HttpException
 
 /**
  * A simple [BaseFragment] subclass.
@@ -39,6 +41,35 @@ class SubmissionTestResultFragment : BaseFragment() {
         return binding.root
     }
 
+    private fun navigateToMainScreen() =
+        doNavigate(SubmissionTestResultFragmentDirections.actionSubmissionResultFragmentToMainFragment())
+
+    private fun buildErrorDialog(exception: Exception): DialogHelper.DialogInstance {
+        return when (exception) {
+            is HttpException -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                getString(
+                    R.string.submission_error_dialog_web_generic_network_error_body,
+                    exception.code()
+                ),
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToMainScreen
+            )
+            else -> DialogHelper.DialogInstance(
+                requireActivity(),
+                R.string.submission_error_dialog_web_generic_error_title,
+                R.string.submission_error_dialog_web_generic_error_body,
+                R.string.submission_error_dialog_web_generic_error_button_positive,
+                null,
+                true,
+                ::navigateToMainScreen
+            )
+        }
+    }
+
     override fun onDestroyView() {
         super.onDestroyView()
         _binding = null
@@ -47,6 +78,12 @@ class SubmissionTestResultFragment : BaseFragment() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
         setButtonOnClickListener()
+
+        submissionViewModel.uiStateError.observe(viewLifecycleOwner, Observer {
+            if (it != null) {
+                DialogHelper.showDialog(buildErrorDialog(it))
+            }
+        })
     }
 
     override fun onResume() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
index de2bb9f5066be22b2fe90cd43af268fde93c8df7..bac24dc8dee99b1908a20fca81357b852e2654db 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
@@ -17,14 +17,26 @@ import java.util.Date
 
 class SubmissionViewModel : ViewModel() {
     private val _scanStatus = MutableLiveData(ScanStatus.STARTED)
+
     private val _registrationState = MutableLiveData(ApiRequestState.IDLE)
+    private val _registrationError = MutableLiveData<Exception?>(null)
+
     private val _uiStateState = MutableLiveData(ApiRequestState.IDLE)
+    private val _uiStateError = MutableLiveData<Exception?>(null)
+
     private val _submissionState = MutableLiveData(ApiRequestState.IDLE)
+    private val _submissionError = MutableLiveData<Exception?>(null)
 
     val scanStatus: LiveData<ScanStatus> = _scanStatus
+
     val registrationState: LiveData<ApiRequestState> = _registrationState
+    val registrationError: LiveData<Exception?> = _registrationError
+
     val uiStateState: LiveData<ApiRequestState> = _uiStateState
+    val uiStateError: LiveData<Exception?> = _uiStateError
+
     val submissionState: LiveData<ApiRequestState> = _submissionState
+    val submissionError: LiveData<Exception?> = _submissionError
 
     val deviceRegistered get() = LocalData.registrationToken() != null
 
@@ -34,13 +46,25 @@ class SubmissionViewModel : ViewModel() {
         SubmissionRepository.deviceUIState
 
     fun submitDiagnosisKeys() =
-        executeRequestWithState(SubmissionService::asyncSubmitExposureKeys, _submissionState)
+        executeRequestWithState(
+            SubmissionService::asyncSubmitExposureKeys,
+            _submissionState,
+            _submissionError
+        )
 
     fun doDeviceRegistration() =
-        executeRequestWithState(SubmissionService::asyncRegisterDevice, _registrationState)
+        executeRequestWithState(
+            SubmissionService::asyncRegisterDevice,
+            _registrationState,
+            _registrationError
+        )
 
     fun refreshDeviceUIState() =
-        executeRequestWithState(SubmissionRepository::refreshUIState, _uiStateState)
+        executeRequestWithState(
+            SubmissionRepository::refreshUIState,
+            _uiStateState,
+            _uiStateError
+        )
 
     fun validateAndStoreTestGUID(scanResult: String) {
         if (SubmissionService.containsValidGUID(scanResult)) {
@@ -65,7 +89,8 @@ class SubmissionViewModel : ViewModel() {
 
     private fun executeRequestWithState(
         apiRequest: suspend () -> Unit,
-        state: MutableLiveData<ApiRequestState>
+        state: MutableLiveData<ApiRequestState>,
+        exceptionLiveData: MutableLiveData<Exception?>? = null
     ) {
         state.value = ApiRequestState.STARTED
         viewModelScope.launch {
@@ -73,6 +98,7 @@ class SubmissionViewModel : ViewModel() {
                 apiRequest()
                 state.value = ApiRequestState.SUCCESS
             } catch (err: Exception) {
+                exceptionLiveData?.value = err
                 state.value = ApiRequestState.FAILED
                 err.report(ExceptionCategory.INTERNAL)
             }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
index 5c07fbd3315290a9e792a23e696fe4533a595747..70bcbddee65cd6034ad29ec7c16e3b0ae9673625 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
@@ -34,6 +34,26 @@ object DialogHelper {
             positiveButtonFunction,
             negativeButtonFunction
         )
+
+        constructor(
+            activity: Activity,
+            title: Int,
+            message: String,
+            positiveButton: Int,
+            negativeButton: Int? = null,
+            cancelable: Boolean? = true,
+            positiveButtonFunction: () -> Unit? = {},
+            negativeButtonFunction: () -> Unit? = {}
+        ) : this(
+            activity,
+            activity.resources.getString(title),
+            message,
+            activity.resources.getString(positiveButton),
+            negativeButton?.let { activity.resources.getString(it) },
+            cancelable,
+            positiveButtonFunction,
+            negativeButtonFunction
+        )
     }
 
     fun showDialog(
diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
index 3cae79a5ca3ee633dfbeeb4d0cc5fd30826d8314..c62db62a70fb78a82e4c3a3878014a3be5f14a48 100644
--- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
+++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
@@ -293,6 +293,11 @@
             android:id="@+id/action_submissionRegisterDeviceFragment_to_submissionResultFragment"
             app:destination="@id/submissionResultFragment"
             app:popUpTo="@id/mainFragment" />
+        <action
+            android:id="@+id/action_submissionRegisterDeviceFragment_to_submissionDispatcherFragment"
+            app:destination="@id/submissionDispatcherFragment"
+            app:popUpTo="@id/submissionDispatcherFragment"
+            app:popUpToInclusive="true" />
     </fragment>
     <fragment
         android:id="@+id/submissionDoneFragment"
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index bd8cd1b5a5d8c6bbea7abbdf92a81f01f71f5de8..6474fed1f768505b1c588fafb9540005d4825b9e 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -543,6 +543,36 @@
              Submission
     ###################################### -->
 
+    <!-- XHED: Dialog title for generic web request error -->
+    <string name="submission_error_dialog_web_generic_error_title">Fehler</string>
+    <!-- XMSG: Dialog body for generic web request network error with status code -->
+    <string name="submission_error_dialog_web_generic_network_error_body">Es ist ein Verbindungsfehler aufgetreten (%1$d).  Bitte versuchen Sie es erneut.</string>
+    <!-- XMSG: Dialog body for generic web request error without status code -->
+    <string name="submission_error_dialog_web_generic_error_body">Es ist ein Verbindungsfehler aufgetreten.  Bitte versuchen Sie es erneut.</string>
+    <!-- XBUT: Positive button for generic web request error -->
+    <string name="submission_error_dialog_web_generic_error_button_positive">Zurück</string>
+
+    <!-- XHED: Dialog title for already paired test error -->
+    <string name="submission_error_dialog_web_test_paired_title">Fehler</string>
+    <!-- XMSG: Dialog body for already paired test error -->
+    <string name="submission_error_dialog_web_test_paired_body">Der QR-Code / Die TAN ist ungültig oder wurde schon verwendet. Bitte versuchen Sie es erneut oder kontaktieren Sie die technische Hotline über App-Informationen → Kontakt.</string>
+    <!-- XBUT: Positive button for already paired test error -->
+    <string name="submission_error_dialog_web_test_paired_button_positive">Zurück</string>
+
+    <!-- XHED: Dialog title for could not create submission tan -->
+    <string name="submission_error_dialog_web_paring_invalid_title">Fehler</string>
+    <!-- XMSG: Dialog body for could not create submission tan -->
+    <string name="submission_error_dialog_web_paring_invalid_body">Es konnte keine Übermittlungs-TAN erstellt werden. Bitte kontaktieren Sie die technische Hotline über App-Informationen → Kontakt.</string>
+    <!-- XBUT: Positive button for could not create submission tan -->
+    <string name="submission_error_dialog_web_paring_invalid_button_positive">Zurück</string>
+
+    <!-- XHED: Dialog title for submission tan invalid -->
+    <string name="submission_error_dialog_web_tan_invalid_title">Fehler</string>
+    <!-- XMSG: Dialog body for submission tan invalid -->
+    <string name="submission_error_dialog_web_tan_invalid_body">Es konnte keine Übermittlungs-TAN erstellt werden. Bitte kontaktieren Sie die technische Hotline über App-Informationen → Kontakt.</string>
+    <!-- XBUT: Positive button for submission tan invalid -->
+    <string name="submission_error_dialog_web_tan_invalid_button_positive">Zurück</string>
+
     <!-- Permission Rationale Dialog -->
     <string name="submission_qr_code_scan_permission_rationale_dialog_headline">Kamera Berechtigung benötigt</string>
     <string name="submission_qr_code_scan_permission_rationale_dialog_body">Bitte erlauben Sie die Autorisierung der Kamera für das Scannen von QR-Codes.</string>
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt
index b4dd3853f5bdd59d5866577ef98ea18b02bd64ec..3a17562f085cf105e1e5822a365318e610f53712 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt
@@ -99,4 +99,4 @@ class RiskLevelCalculationTest {
             .setAttenuationDurations(intArray)
             .build()
     }
-}
\ No newline at end of file
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
index 4d0c06f803f98f441e216e1e6ddaf9723c6c54bf..16f069c15ba8d80bfbe487d13fa58ac088362843 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
@@ -21,7 +21,7 @@ class VerificationServiceTest {
             equalTo(false)
         )
     }
-    
+
     @Test
     fun extractGUID() {
         val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"