diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
index a81018bd088121ed7bc25eca0b133c732ef5e7c7..3190d0e48d53526dc44393b0a31e190ea60cd90d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
@@ -58,6 +58,7 @@ object SubmissionRepository {
                 TestResult.POSITIVE -> DeviceUIState.PAIRED_POSITIVE
                 TestResult.PENDING -> DeviceUIState.PAIRED_NO_RESULT
                 TestResult.INVALID -> DeviceUIState.PAIRED_ERROR
+                TestResult.REDEEMED -> DeviceUIState.PAIRED_REDEEMED
             }
         } catch (err: NoRegistrationTokenSetException) {
             return DeviceUIState.UNPAIRED
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 41c8ace277433609dc6740c2fa531be9a8ca0273..03aecc8b20e2803224d0dcdb03772e76f2a3c42d 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
@@ -9,6 +9,7 @@ import android.view.accessibility.AccessibilityEvent
 import androidx.activity.OnBackPressedCallback
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
 import androidx.navigation.fragment.findNavController
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultBinding
@@ -18,6 +19,7 @@ import de.rki.coronawarnapp.exception.http.CwaWebException
 import de.rki.coronawarnapp.ui.doNavigate
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
+import de.rki.coronawarnapp.util.DeviceUIState
 import de.rki.coronawarnapp.util.DialogHelper
 import de.rki.coronawarnapp.util.observeEvent
 
@@ -115,6 +117,23 @@ class SubmissionTestResultFragment : Fragment() {
         submissionViewModel.uiStateError.observeEvent(viewLifecycleOwner) {
             DialogHelper.showDialog(buildErrorDialog(it))
         }
+
+        submissionViewModel.deviceUiState.observe(viewLifecycleOwner, Observer { uiState ->
+            if (uiState == DeviceUIState.PAIRED_REDEEMED) {
+                showRedeemedTokenWarningDialog()
+            }
+        })
+    }
+
+    private fun showRedeemedTokenWarningDialog() {
+        val dialog = DialogHelper.DialogInstance(
+            requireActivity(),
+            R.string.submission_error_dialog_web_tan_redeemed_title,
+            R.string.submission_error_dialog_web_tan_redeemed_body,
+            R.string.submission_error_dialog_web_tan_redeemed_button_positive
+        )
+
+        DialogHelper.showDialog(dialog)
     }
 
     override fun onResume() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DeviceUIState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DeviceUIState.kt
index 6049195d48cd55a2a46cdba6440d145f6c6f8e2c..bc304ab27c4a7eadac06adb6decadd14c4c97fac 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DeviceUIState.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DeviceUIState.kt
@@ -7,6 +7,7 @@ enum class DeviceUIState {
     PAIRED_POSITIVE_TELETAN,
     PAIRED_NEGATIVE,
     PAIRED_ERROR,
+    PAIRED_REDEEMED,
     SUBMITTED_INITIAL,
     SUBMITTED_FINAL
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
index 5d93578b11d500499650e901cb517d0b087e4cb7..fb6de1ec97bf660e2481d4512f269fd44966a962 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
@@ -64,7 +64,8 @@ fun formatTestResultCardContent(uiState: DeviceUIState?): Spannable {
     return when (uiState) {
         DeviceUIState.PAIRED_NO_RESULT ->
             SpannableString(appContext.getString(R.string.test_result_card_status_pending))
-        DeviceUIState.PAIRED_ERROR ->
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED ->
             SpannableString(appContext.getString(R.string.test_result_card_status_invalid))
 
         DeviceUIState.PAIRED_POSITIVE,
@@ -81,7 +82,8 @@ fun formatTestStatusIcon(uiState: DeviceUIState?): Drawable? {
         DeviceUIState.PAIRED_POSITIVE_TELETAN,
         DeviceUIState.PAIRED_POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive)
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_negative)
-        DeviceUIState.PAIRED_ERROR -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
         else -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
     }
 }
@@ -102,13 +104,14 @@ fun formatTestResultPositiveStepsVisible(uiState: DeviceUIState?): Int =
     formatVisibility(uiState == DeviceUIState.PAIRED_POSITIVE || uiState == DeviceUIState.PAIRED_POSITIVE_TELETAN)
 
 fun formatTestResultInvalidStepsVisible(uiState: DeviceUIState?): Int =
-    formatVisibility(uiState == DeviceUIState.PAIRED_ERROR)
+    formatVisibility(uiState == DeviceUIState.PAIRED_ERROR || uiState == DeviceUIState.PAIRED_REDEEMED)
 
 fun formatSubmissionStatusCardSubtitleColor(uiState: DeviceUIState?): Int {
     val appContext = CoronaWarnApplication.getAppContext()
     return when (uiState) {
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getColor(R.color.colorTextSemanticGreen)
-        DeviceUIState.PAIRED_ERROR -> appContext.getColor(R.color.colorTextSemanticNeutral)
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED -> appContext.getColor(R.color.colorTextSemanticNeutral)
         else -> appContext.getColor(R.color.colorTextPrimary1)
     }
 }
@@ -117,7 +120,8 @@ fun formatSubmissionStatusCardSubtitleText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
     return when (uiState) {
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.submission_status_card_subtitle_negative)
-        DeviceUIState.PAIRED_ERROR -> appContext.getString(R.string.submission_status_card_subtitle_invalid)
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED -> appContext.getString(R.string.submission_status_card_subtitle_invalid)
         else -> ""
     }
 }
@@ -126,6 +130,7 @@ fun formatSubmissionStatusCardContentTitleText(uiState: DeviceUIState?): String
     val appContext = CoronaWarnApplication.getAppContext()
     return when (uiState) {
         DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED,
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.submission_status_card_title_available)
         DeviceUIState.PAIRED_NO_RESULT -> appContext.getString(R.string.submission_status_card_title_pending)
         else -> appContext.getString(R.string.submission_status_card_title_pending)
@@ -135,7 +140,8 @@ fun formatSubmissionStatusCardContentTitleText(uiState: DeviceUIState?): String
 fun formatSubmissionStatusCardContentBodyText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
     return when (uiState) {
-        DeviceUIState.PAIRED_ERROR -> appContext.getString(R.string.submission_status_card_body_invalid)
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED -> appContext.getString(R.string.submission_status_card_body_invalid)
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.submission_status_card_body_negative)
         DeviceUIState.PAIRED_NO_RESULT -> appContext.getString(R.string.submission_status_card_body_pending)
         else -> appContext.getString(R.string.submission_status_card_body_pending)
@@ -145,6 +151,7 @@ fun formatSubmissionStatusCardContentBodyText(uiState: DeviceUIState?): String {
 fun formatSubmissionStatusCardContentStatusTextVisible(uiState: DeviceUIState?): Int {
     return when (uiState) {
         DeviceUIState.PAIRED_NEGATIVE,
+        DeviceUIState.PAIRED_REDEEMED,
         DeviceUIState.PAIRED_ERROR -> View.VISIBLE
         else -> View.GONE
     }
@@ -157,7 +164,8 @@ fun formatSubmissionStatusCardContentIcon(uiState: DeviceUIState?): Drawable? {
         DeviceUIState.PAIRED_POSITIVE,
         DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getDrawable(R.drawable.ic_main_illustration_pending)
         DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_negative)
-        DeviceUIState.PAIRED_ERROR -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_REDEEMED -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
         else -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
     }
 }
@@ -180,7 +188,8 @@ fun formatSubmissionStatusCardContentVisible(
 ): Int = formatVisibility(
     deviceUiState == DeviceUIState.PAIRED_ERROR ||
             deviceUiState == DeviceUIState.PAIRED_NEGATIVE ||
-            deviceUiState == DeviceUIState.PAIRED_NO_RESULT
+            deviceUiState == DeviceUIState.PAIRED_NO_RESULT ||
+            deviceUiState == DeviceUIState.PAIRED_REDEEMED
 )
 
 fun formatShowSubmissionStatusPositiveCard(deviceUiState: DeviceUIState?): Int =
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/TestResult.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/TestResult.kt
index 31ec1a64d5ebf138836d478eff3a642000ee6ced..c0cacc40a79d73c32ce47d9f4863df2c6f8bc1e9 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/TestResult.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/TestResult.kt
@@ -5,7 +5,8 @@ enum class TestResult(val value: Int) {
     PENDING(0),
     NEGATIVE(1),
     POSITIVE(2),
-    INVALID(3);
+    INVALID(3),
+    REDEEMED(4);
 
     companion object {
         fun fromInt(value: Int) = values().first { it.value == value }
diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml
index 599eb7de369d68434332d8d51a5d05510b76fd33..227eb515bec4b635fded2e0e3e7b2ddfc943dfc3 100644
--- a/Corona-Warn-App/src/main/res/values-de/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-de/strings.xml
@@ -726,6 +726,13 @@
     <!-- XBUT: Positive button for submission tan invalid -->
     <string name="submission_error_dialog_web_tan_invalid_button_positive">"Zurück"</string>
 
+    <!-- XHED: Dialog title for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_title">"Test fehlerhaft"</string>
+    <!-- XMSG: Dialog body for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_body">"Es gab ein Problem bei der Auswertung Ihres Tests. Ihr QR Code ist bereits abgelaufen."</string>
+    <!-- XBUT: Positive button for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string>
+
     <!-- Permission Rationale Dialog -->
     <!-- XHED: Dialog headline QR Scan permission rationale  -->
     <string name="submission_qr_code_scan_permission_rationale_dialog_headline">"Kamera-Zugriff benötigt"</string>
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index 82541082b881b092b1896af6a2d3939b7b4be3d0..60485feb00b45074a4caf7a71f12c0b856ad5f59 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -728,6 +728,13 @@
     <!-- XBUT: Positive button for submission tan invalid -->
     <string name="submission_error_dialog_web_tan_invalid_button_positive">"Back"</string>
 
+    <!-- XHED: Dialog title for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_title">"Test has errors"</string>
+    <!-- XMSG: Dialog body for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_body">"There was a problem evaluating your test. Your QR Code has already expired."</string>
+    <!-- XBUT: Positive button for submission tan redeemed -->
+    <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string>
+
     <!-- Permission Rationale Dialog -->
     <!-- XHED: Dialog headline QR Scan permission rationale  -->
     <string name="submission_qr_code_scan_permission_rationale_dialog_headline">"Camera authorization required"</string>