diff --git a/core/modules/taxonomy/config/schema/taxonomy.views.schema.yml b/core/modules/taxonomy/config/schema/taxonomy.views.schema.yml
index 9ec9758185..4f22d6fb81 100644
--- a/core/modules/taxonomy/config/schema/taxonomy.views.schema.yml
+++ b/core/modules/taxonomy/config/schema/taxonomy.views.schema.yml
@@ -139,7 +139,7 @@ views.filter.taxonomy_index_tid:
       type: sequence
       label: 'Values'
       sequence:
-        type: integer
+        type: string
         label: 'Value'
 
 views.filter.taxonomy_index_tid_depth:
diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
index 76c9635559..999a3bf0a0 100644
--- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
+++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php
@@ -5,7 +5,9 @@
 use Drupal\Core\Entity\Element\EntityAutocomplete;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Component\Uuid\Uuid;
 use Drupal\taxonomy\Entity\Term;
+use Drupal\taxonomy\TermInterface;
 use Drupal\taxonomy\TermStorageInterface;
 use Drupal\taxonomy\VocabularyStorageInterface;
 use Drupal\views\ViewExecutable;
@@ -95,6 +97,10 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
+    if (!empty($options['value'])) {
+      $options['value'] = $this->getEntityIdsFromUuids($options['value']);
+    }
+
     parent::init($view, $display, $options);
 
     if (!empty($this->definition['vocabulary'])) {
@@ -102,6 +108,33 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o
     }
   }
 
+  /**
+   * Get entity IDs from UUIDs.
+   *
+   * @param array $uuids
+   *   UUIDs to retrieve entity IDs for.
+   *
+   * @return array
+   *   Entity IDs for the given UUIDs.
+   */
+  protected function getEntityIdsFromUuids(array $uuids) {
+    foreach ($uuids as $uuid) {
+      if (!Uuid::isValid($uuid)) {
+        // Abandon conversion if we already have IDs and not UUIDs.
+        return $uuids;
+      }
+    }
+
+    $terms = $this->termStorage->loadByProperties(['uuid' => $uuids]);
+
+    $entity_ids = [];
+    foreach ($terms as $term) {
+      $entity_ids[$term->id()] = $term->id();
+    }
+
+    return $entity_ids;
+  }
+
   public function hasExtraOptions() {
     return TRUE;
   }
@@ -170,7 +203,7 @@ public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
   }
 
   protected function valueForm(&$form, FormStateInterface $form_state) {
-    $vocabulary = $this->vocabularyStorage->load($this->options['vid']);
+    $vocabulary = $this->getVocabulary();
     if (empty($vocabulary) && $this->options['limit']) {
       $form['markup'] = [
         '#markup' => '<div class="js-form-item form-item">' . $this->t('An invalid vocabulary is selected. Please change it in the options.') . '</div>',
@@ -179,58 +212,10 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
     }
 
     if ($this->options['type'] == 'textfield') {
-      $terms = $this->value ? Term::loadMultiple(($this->value)) : [];
-      $form['value'] = [
-        '#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
-        '#type' => 'textfield',
-        '#default_value' => EntityAutocomplete::getEntityLabels($terms),
-      ];
-
-      if ($this->options['limit']) {
-        $form['value']['#type'] = 'entity_autocomplete';
-        $form['value']['#target_type'] = 'taxonomy_term';
-        $form['value']['#selection_settings']['target_bundles'] = [$vocabulary->id()];
-        $form['value']['#tags'] = TRUE;
-        $form['value']['#process_default_value'] = FALSE;
-      }
+      $form['value'] = $this->getFormValueForTextFields();
     }
     else {
-      if (!empty($this->options['hierarchy']) && $this->options['limit']) {
-        $tree = $this->termStorage->loadTree($vocabulary->id(), 0, NULL, TRUE);
-        $options = [];
-
-        if ($tree) {
-          foreach ($tree as $term) {
-            if (!$term->isPublished() && !$this->currentUser->hasPermission('administer taxonomy')) {
-              continue;
-            }
-            $choice = new \stdClass();
-            $choice->option = [$term->id() => str_repeat('-', $term->depth) . \Drupal::service('entity.repository')->getTranslationFromContext($term)->label()];
-            $options[] = $choice;
-          }
-        }
-      }
-      else {
-        $options = [];
-        $query = \Drupal::entityQuery('taxonomy_term')
-          ->accessCheck(TRUE)
-          // @todo Sorting on vocabulary properties -
-          //   https://www.drupal.org/node/1821274.
-          ->sort('weight')
-          ->sort('name')
-          ->addTag('taxonomy_term_access');
-        if (!$this->currentUser->hasPermission('administer taxonomy')) {
-          $query->condition('status', 1);
-        }
-        if ($this->options['limit']) {
-          $query->condition('vid', $vocabulary->id());
-        }
-        $terms = Term::loadMultiple($query->execute());
-        foreach ($terms as $term) {
-          $options[$term->id()] = \Drupal::service('entity.repository')->getTranslationFromContext($term)->label();
-        }
-      }
-
+      $options = $this->getFormValueOptions();
       $default_value = (array) $this->value;
 
       if ($exposed = $form_state->get('exposed')) {
@@ -245,22 +230,7 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
         }
 
         if (empty($this->options['expose']['multiple'])) {
-          if (empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce']))) {
-            $default_value = 'All';
-          }
-          elseif (empty($default_value)) {
-            $keys = array_keys($options);
-            $default_value = array_shift($keys);
-          }
-          // Due to #1464174 there is a chance that array('') was saved in the admin ui.
-          // Let's choose a safe default value.
-          elseif ($default_value == ['']) {
-            $default_value = 'All';
-          }
-          else {
-            $copy = $default_value;
-            $default_value = array_shift($copy);
-          }
+          $default_value = $this->getDefaultValueForSingleExposedOption($default_value, $options);
         }
       }
       $form['value'] = [
@@ -288,6 +258,117 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
     }
   }
 
+  /**
+   * Get the form value for text fields.
+   *
+   * @return array
+   *   Form API render array for text fields.
+   */
+  protected function getFormValueForTextFields() {
+    $vocabulary = $this->getVocabulary();
+    $terms = $this->value ? Term::loadMultiple($this->value) : [];
+    $form_value = [
+      '#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
+      '#type' => 'textfield',
+      '#default_value' => EntityAutocomplete::getEntityLabels($terms),
+    ];
+    if ($this->options['limit']) {
+      $form_value['#type'] = 'entity_autocomplete';
+      $form_value['#target_type'] = 'taxonomy_term';
+      $form_value['#selection_settings']['target_bundles'] = [$vocabulary->id()];
+      $form_value['#tags'] = TRUE;
+      $form_value['#process_default_value'] = FALSE;
+    }
+    return $form_value;
+  }
+
+  protected function getFormValueOptions() {
+    if (!empty($this->options['hierarchy']) && $this->options['limit']) {
+      return $this->getFormValueOptionsWithHierarchyAndLimit();
+    }
+    return $this->getFormValueOptionsWithoutHierarchyAndLimit();
+  }
+
+  /**
+   * Get the form value for vocabulary terms with hierarchy and limit.
+   *
+   * @return array
+   *   Form API render array for text fields.
+   */
+  protected function getFormValueOptionsWithHierarchyAndLimit() {
+    $tree = $this->termStorage->loadTree($this->getVocabulary()->id(), 0, NULL, TRUE);
+    $options = [];
+
+    if ($tree) {
+      foreach ($tree as $term) {
+        if (!$term->isPublished() && !$this->currentUser->hasPermission('administer taxonomy')) {
+          continue;
+        }
+        $choice = new \stdClass();
+        $choice->option = [$term->id() => str_repeat('-', $term->depth) . $this->getTermLabel($term)];
+        $options[] = $choice;
+      }
+    }
+    return $options;
+  }
+
+  /**
+   * Get the form value for vocabulary terms without hierarchy, with limit.
+   *
+   * @return array
+   *   Form API render array for text fields.
+   */
+  protected function getFormValueOptionsWithoutHierarchyAndLimit() {
+    $options = [];
+
+    $query = \Drupal::entityQuery('taxonomy_term')
+      ->accessCheck(TRUE)
+      // @todo Sorting on vocabulary properties -
+      //   https://www.drupal.org/node/1821274.
+      ->sort('weight')
+      ->sort('name')
+      ->addTag('taxonomy_term_access');
+
+    if (!$this->currentUser->hasPermission('administer taxonomy')) {
+      $query->condition('status', 1);
+    }
+    if ($this->options['limit']) {
+      $query->condition('vid', $this->getVocabulary()->id());
+    }
+
+    foreach (Term::loadMultiple($query->execute()) as $term) {
+      $options[$term->id()] = $this->getTermLabel($term);
+    }
+    return $options;
+  }
+
+  /**
+   * Get the appropriate default value for the given exposed option.
+   *
+   * @param array $default_value
+   *   The stored default value from the value form.
+   * @param array $options
+   *   The available options.
+   *
+   * @return string
+   *   The default value matching the available options.
+   */
+  protected function getDefaultValueForSingleExposedOption(array $default_value, array $options) {
+    switch (TRUE) {
+      case empty($this->options['expose']['required']) && (empty($default_value) || !empty($this->options['expose']['reduce'])):
+      case $default_value == ['']:
+        return 'All';
+
+      case empty($default_value):
+        $keys = array_keys($options);
+        return array_shift($keys);
+
+      default:
+        $copy = $default_value;
+        return array_shift($copy);
+    }
+  }
+
   protected function valueValidate($form, FormStateInterface $form_state) {
     // We only validate if they've chosen the text field style.
     if ($this->options['type'] != 'textfield') {
@@ -376,6 +457,14 @@ public function validateExposed(&$form, FormStateInterface $form_state) {
 
   protected function valueSubmit($form, FormStateInterface $form_state) {
     // prevent array_filter from messing up our arrays in parent submit.
+    $term_ids = $form_state->getValue(['options', 'value']);
+
+    $uuids = [];
+    foreach ($this->termStorage->loadMultiple($term_ids) as $term) {
+      $uuids[] = $term->uuid();
+    }
+
+    $form_state->setValue(['options', 'value'], $uuids);
   }
 
   public function buildExposeForm(&$form, FormStateInterface $form_state) {
@@ -398,7 +487,7 @@ public function adminSummary() {
       $this->value = array_filter($this->value);
       $terms = Term::loadMultiple($this->value);
       foreach ($terms as $term) {
-        $this->valueOptions[$term->id()] = \Drupal::service('entity.repository')->getTranslationFromContext($term)->label();
+        $this->valueOptions[$term->id()] = $this->getTermLabel($term);
       }
     }
     return parent::adminSummary();
@@ -423,8 +512,9 @@ public function getCacheContexts() {
   public function calculateDependencies() {
     $dependencies = parent::calculateDependencies();
 
-    $vocabulary = $this->vocabularyStorage->load($this->options['vid']);
-    $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName();
+    if ($vocabulary = $this->getVocabulary()) {
+      $dependencies[$vocabulary->getConfigDependencyKey()][] = $vocabulary->getConfigDependencyName();
+    }
 
     foreach ($this->termStorage->loadMultiple($this->options['value']) as $term) {
       $dependencies[$term->getConfigDependencyKey()][] = $term->getConfigDependencyName();
@@ -433,4 +523,27 @@ public function calculateDependencies() {
     return $dependencies;
   }
 
+  /**
+   * Get the vocabulary entity given a vocabulary ID.
+   *
+   * @return \Drupal\taxonomy\VocabularyInterface
+   *   The vocabulary matching the given vocabulary ID.
+   */
+  protected function getVocabulary() {
+    return $this->vocabularyStorage->load($this->options['vid']);
+  }
+
+  /**
+   * Get the translated term label given a term entity.
+   *
+   * @param \Drupal\taxonomy\TermInterface $term
+   *   The term to get the label from.
+   *
+   * @return string
+   *   The term label.
+   */
+  protected function getTermLabel(TermInterface $term) {
+    return \Drupal::service('entity.repository')->getTranslationFromContext($term)->label();
+  }
+
 }
diff --git a/core/modules/taxonomy/taxonomy.post_update.php b/core/modules/taxonomy/taxonomy.post_update.php
index f261092d0e..518c0b0b67 100644
--- a/core/modules/taxonomy/taxonomy.post_update.php
+++ b/core/modules/taxonomy/taxonomy.post_update.php
@@ -5,6 +5,10 @@
  * Post update functions for Taxonomy.
  */
 
+use Drupal\Component\Uuid\Uuid;
+use Drupal\Core\Config\Entity\ConfigEntityUpdater;
+use Drupal\taxonomy\Entity\Term;
+
 /**
  * Implements hook_removed_post_updates().
  */
@@ -25,3 +29,54 @@ function taxonomy_removed_post_updates() {
 function taxonomy_post_update_clear_views_argument_validator_plugins_cache(): void {
   // An empty update will flush all caches.
 }
+
+/**
+ * Update views filters to use UUIDs for term IDs instead of entity IDs.
+ */
+function taxonomy_post_update_convert_term_views_filters_to_uuids(&$sandbox = NULL) {
+  if (!\Drupal::moduleHandler()->moduleExists('views')) {
+    return;
+  }
+
+  \Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'view', function ($view) {
+    /** @var \Drupal\views\ViewEntityInterface $view */
+    $displays = $view->get('display');
+
+    foreach ($displays as &$display) {
+      $filters = $display['display_options']['filters'] ?? [];
+      foreach ($filters as $id => $filter) {
+        if ($filter['plugin_id'] === 'taxonomy_index_tid' && isset($filter['value'])) {
+          $filters[$id]['value'] = taxonomy_convert_entity_ids_to_uuids($filters[$id]['value']);
+        }
+      }
+
+      $display['display_options']['filters'] = $filters;
+    }
+    $view->set('display', $displays);
+    return TRUE;
+  });
+}
+
+/**
+ * Convert entity IDs to UUIDs.
+ *
+ * @param array $entity_ids
+ *   Entity IDs to retrieve UUIDs for.
+ *
+ * @return array
+ *   UUIDs for the given entity IDs.
+ */
+function taxonomy_convert_entity_ids_to_uuids(array $entity_ids) {
+  $uuids = [];
+
+  foreach ($entity_ids as $entity_id) {
+    if (Uuid::isValid($entity_id)) {
+      // This ID is already a UUID.
+      $uuids[] = $entity_id;
+      continue;
+    }
+    $uuids[] = Term::load($entity_id)->uuid();
+  }
+
+  return $uuids;
+}
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
index be15a8f3e7..facff619f4 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid.yml
@@ -134,7 +134,7 @@ display:
           admin_label: ''
           operator: or
           value:
-            - 2
+            - '3dec3e87-5e46-455d-b49c-1695fb74b756'
           group: 1
           exposed: false
           expose:
diff --git a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
index ea9f640813..4a835ab595 100644
--- a/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
+++ b/core/modules/taxonomy/tests/modules/taxonomy_test_views/test_views/views.view.test_filter_taxonomy_index_tid__non_existing_dependency.yml
@@ -134,8 +134,8 @@ display:
           admin_label: ''
           operator: or
           value:
-            - 3
-            - 4
+            - '3'
+            - '4'
           group: 1
           exposed: false
           expose:
diff --git a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
index 89c93a465a..1e552534e0 100644
--- a/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
+++ b/core/modules/taxonomy/tests/src/Functional/Views/TaxonomyIndexTidUiTest.php
@@ -132,9 +132,6 @@ public function testFilterUI() {
       'config' => [
         'taxonomy.vocabulary.tags',
       ],
-      'content' => [
-        'taxonomy_term:tags:' . Term::load(2)->uuid(),
-      ],
       'module' => [
         'node',
         'taxonomy',
@@ -167,6 +164,12 @@ public function testExposedFilter() {
       $field_name => [['target_id' => $this->terms[2][0]->id()]],
     ]);
 
+    // Set the selected term to Term 1.0.
+    $this->drupalGet('admin/structure/views/nojs/handler/test_filter_taxonomy_index_tid/default/filter/tid');
+    $this->submitForm(['options[value][]' => [2]], 'Apply');
+    // Save the view.
+    $this->submitForm([], 'Save');
+
     // Only the nodes with the selected term should be shown.
     $this->drupalGet('test-filter-taxonomy-index-tid');
     $this->assertSession()->pageTextNotContains($node1->getTitle());
