diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
index a1188ed16b48a8ecb8699747c35fcb185c02bec3..ea5639dcf24bd5623df3b9c46def5c4671769445 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanFragment.kt
@@ -7,6 +7,7 @@ import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
+import androidx.fragment.app.viewModels
 import androidx.navigation.fragment.findNavController
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionTanBinding
@@ -18,14 +19,17 @@ import de.rki.coronawarnapp.ui.doNavigate
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.util.DialogHelper
+import de.rki.coronawarnapp.util.TanHelper
 import de.rki.coronawarnapp.util.observeEvent
+import kotlinx.android.synthetic.main.include_submission_tan.submission_tan_error
+import kotlinx.android.synthetic.main.include_submission_tan.submission_tan_character_error
 
 /**
  * Fragment for TAN entry
  */
 class SubmissionTanFragment : Fragment() {
 
-    private val viewModel: SubmissionTanViewModel by activityViewModels()
+    private val viewModel: SubmissionTanViewModel by viewModels()
     private val submissionViewModel: SubmissionViewModel by activityViewModels()
     private var _binding: FragmentSubmissionTanBinding? = null
     private val binding: FragmentSubmissionTanBinding get() = _binding!!
@@ -97,8 +101,20 @@ class SubmissionTanFragment : Fragment() {
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        binding.submissionTanContent.submissionTanInput.listener =
-            { tan -> viewModel.tan.value = tan }
+        binding.submissionTanContent.submissionTanInput.listener = { tan ->
+            resetError()
+
+            viewModel.tan.value = tan
+
+            if (tan != null) {
+                if (!TanHelper.allCharactersValid(tan))
+                    showCharacterError()
+
+                if (tan.length == TanConstants.MAX_LENGTH && !TanHelper.isChecksumValid(tan))
+                    showTanError()
+            }
+        }
+
         binding.submissionTanButtonEnter.setOnClickListener { storeTanAndContinue() }
         binding.submissionTanHeader.headerButtonBack.buttonIcon.setOnClickListener { goBack() }
 
@@ -120,6 +136,19 @@ class SubmissionTanFragment : Fragment() {
         })
     }
 
+    private fun resetError() {
+        submission_tan_character_error.visibility = View.GONE
+        submission_tan_error.visibility = View.GONE
+    }
+
+    private fun showCharacterError() {
+        submission_tan_character_error.visibility = View.VISIBLE
+    }
+
+    private fun showTanError() {
+        submission_tan_error.visibility = View.VISIBLE
+    }
+
     override fun onResume() {
         super.onResume()
         binding.submissionTanRoot.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
index e42d6c9a2cffd5d8aabe28d4cbca5c6a2b4dd3a2..849aebddf36ed17417e72c4ad8c73c1506ca0fc0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
@@ -23,17 +23,6 @@ class SubmissionTanViewModel : ViewModel() {
                     TanHelper.allCharactersValid(it)
         }
 
-    val tanChecksumValid =
-        Transformations.map(tan) {
-            ((it !== null && it.trim().length == TanConstants.MAX_LENGTH) &&
-                    TanHelper.isChecksumValid(it).not()).not()
-        }
-
-    val tanCharactersValid =
-        Transformations.map(tan) {
-            !((it != null) && TanHelper.allCharactersValid(it).not())
-        }
-
     fun storeTeletan() {
         val teletan = tan.value!!
         Timber.d("Storing teletan $teletan")
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
index 66b26f262dcb2c50e612abc584a8aca9834b967e..91a3e227e730b652d2a98bdb9cf2b9f915358106 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/TanInput.kt
@@ -14,7 +14,6 @@ import androidx.core.view.children
 import androidx.core.widget.doOnTextChanged
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.ui.submission.TanConstants
-import de.rki.coronawarnapp.ui.submission.TanConstants.MAX_LENGTH
 import de.rki.coronawarnapp.util.TanHelper
 import kotlinx.android.synthetic.main.view_tan_input_edittext.view.tan_input_edittext
 import java.util.Locale
@@ -40,7 +39,7 @@ class TanInput(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs
             TanConstants.ALPHA_NUMERIC_CHARS.contains(it)
         }
     }
-    private var lengthFilter = InputFilter.LengthFilter(MAX_LENGTH)
+    private var lengthFilter = InputFilter.LengthFilter(TanConstants.MAX_LENGTH)
 
     var listener: ((String?) -> Unit)? = null
 
@@ -78,20 +77,9 @@ class TanInput(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs
         }
     }
 
-    private fun limitLength(length: Int?) {
-        lengthFilter = InputFilter.LengthFilter(if (length != null) length else MAX_LENGTH)
-        tan_input_edittext.filters = arrayOf(whitespaceFilter, alphaNumericFilter, lengthFilter)
-    }
-
     private fun updateTan(text: CharSequence?) {
         this.tan = text?.toString()?.toUpperCase(Locale.ROOT)
         updateDigits()
-        tan?.let {
-            limitLength(
-                if (TanHelper.allCharactersValid(it)) null
-                else it.length
-            )
-        }
         notifyListener()
     }
 
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml b/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
index b86713c29c6865f66be70d38e61475cd142113e0..e1b02f87c6ae918d87c68cd9ab4e288b091044e6 100644
--- a/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_tan.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
 
     <data>
 
@@ -52,10 +53,11 @@
                 android:accessibilityLiveRegion="assertive"
                 android:text="@string/submission_tan_character_error"
                 android:textColor="@color/colorTextSemanticRed"
-                android:visibility="@{FormatterSubmissionHelper.formatShowTanCharacterError(viewmodel.tanCharactersValid, viewmodel.tanChecksumValid)}"
+                android:visibility="gone"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/submission_tan_input" />
+                app:layout_constraintTop_toBottomOf="@id/submission_tan_input"
+                tools:visibility="visible" />
 
             <TextView
                 android:id="@+id/submission_tan_error"
@@ -66,10 +68,11 @@
                 android:accessibilityLiveRegion="assertive"
                 android:text="@string/submission_tan_error"
                 android:textColor="@color/colorTextSemanticRed"
-                android:visibility="@{FormatterHelper.formatVisibility(!viewmodel.tanChecksumValid)}"
+                android:visibility="gone"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/submission_tan_input" />
+                app:layout_constraintTop_toBottomOf="@id/submission_tan_character_error"
+                tools:visibility="visible" />
 
             <include layout="@layout/merge_guidelines_side" />
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
index 96973d9dc6cb3098ca91507c7e7bc8d01b785b03..805e975068920ae3916e0fc6f42bfa0cdfb12eb8 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModelTest.kt
@@ -14,15 +14,6 @@ import org.junit.Test
 class SubmissionTanViewModelTest {
     private var viewModel: SubmissionTanViewModel = SubmissionTanViewModel()
 
-    @Test
-    fun allCharactersValid() {
-        viewModel.tan.postValue("ABCD")
-        viewModel.tanCharactersValid.value?.let { assertTrue(it) }
-
-        viewModel.tan.postValue("ABCD0")
-        viewModel.tanCharactersValid.value?.let { assertFalse(it) }
-    }
-
     @Test
     fun tanFormatValid() {
         viewModel.tan.postValue("ZWFPC7NG47")
@@ -38,15 +29,6 @@ class SubmissionTanViewModelTest {
         viewModel.isValidTanFormat.value?.let { assertFalse(it) }
     }
 
-    @Test
-    fun checksumValid() {
-        viewModel.tan.postValue("ZWFPC7NG47")
-        viewModel.tanChecksumValid.value?.let { assertTrue(it) }
-
-        viewModel.tan.postValue("ZWFPC7NG48")
-        viewModel.tanChecksumValid.value?.let { assertFalse(it) }
-    }
-
     @Test
     fun testTanStorage() {
         val sr = mockk<SubmissionRepository> {