diff --git a/core/lib/Drupal/Core/Datetime/Element/Datelist.php b/core/lib/Drupal/Core/Datetime/Element/Datelist.php
index d81f39a3eb..7eb51a603d 100644
--- a/core/lib/Drupal/Core/Datetime/Element/Datelist.php
+++ b/core/lib/Drupal/Core/Datetime/Element/Datelist.php
@@ -173,6 +173,9 @@ public static function valueCallback(&$element, $input, FormStateInterface $form
    * @return array
    */
   public static function processDatelist(&$element, FormStateInterface $form_state, &$complete_form) {
+    // Remove the type from the wrapper of the expanded elements.
+    unset($element['#type']);
+
     // Load translated date part labels from the appropriate calendar plugin.
     $date_helper = new DateHelper();
 
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
index b623c8755e..7e1043ddb5 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
@@ -31,6 +31,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
 
     $element += [
       '#type' => 'select',
+      '#title' => '@todo',
       '#options' => $this->getOptions($items->getEntity()),
       '#default_value' => $this->getSelectedOptions($items),
       // Do not display a 'multiple' select box if there is only one option.
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index d64c1df5b8..8d94116dd0 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -998,6 +998,21 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
       }
       $element['#processed'] = TRUE;
     }
+    $types_to_skip = [
+      'field_ui_table',
+      'table',
+      'tableselect',
+      'hidden',
+      'token',
+      'value',
+      'item',
+    ];
+    if (isset($element['#type']) && !in_array($element['#type'], $types_to_skip) && !empty($element['#input']) && empty($element['#attributes']['aria-labelledby'])) {
+      $title_key = in_array($element['#type'], ['button', 'submit']) ? '#value' : '#title';
+      if (!isset($element[$title_key])) {
+        @trigger_error(sprintf('Form elements must have a #title attribute as of Drupal 9.0.0. Form element "%s" of #type "%s" from form "%s" is missing a #title attribute.', implode('][', $element['#array_parents']), $element['#type'], $form_id), E_USER_DEPRECATED);
+      }
+    }
 
     // We start off assuming all form elements are in the correct order.
     $element['#sorted'] = TRUE;
diff --git a/core/lib/Drupal/Core/Render/Element/PasswordConfirm.php b/core/lib/Drupal/Core/Render/Element/PasswordConfirm.php
index 07c31490f4..a9c6512138 100644
--- a/core/lib/Drupal/Core/Render/Element/PasswordConfirm.php
+++ b/core/lib/Drupal/Core/Render/Element/PasswordConfirm.php
@@ -17,7 +17,6 @@
  * @code
  * $form['pass'] = array(
  *   '#type' => 'password_confirm',
- *   '#title' => $this->t('Password'),
  *   '#size' => 25,
  * );
  * @endcode
@@ -68,6 +67,9 @@ public static function valueCallback(&$element, $input, FormStateInterface $form
    * Expand a password_confirm field into two text boxes.
    */
   public static function processPasswordConfirm(&$element, FormStateInterface $form_state, &$complete_form) {
+    // Remove the type from the wrapper of the expanded elements.
+    unset($element['#type']);
+
     $element['pass1'] = [
       '#type' => 'password',
       '#title' => t('Password'),
diff --git a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestSettingsValidationBlock.php b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestSettingsValidationBlock.php
index d1f16d7fda..41f78fbc0c 100644
--- a/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestSettingsValidationBlock.php
+++ b/core/modules/block/tests/modules/block_test/src/Plugin/Block/TestSettingsValidationBlock.php
@@ -19,7 +19,12 @@ class TestSettingsValidationBlock extends BlockBase {
    * {@inheritdoc}
    */
   public function blockForm($form, FormStateInterface $form_state) {
-    return ['digits' => ['#type' => 'textfield']] + $form;
+    return [
+      'digits' => [
+        '#type' => 'textfield',
+        '#title' => 'Digits',
+      ],
+    ] + $form;
   }
 
   /**
diff --git a/core/modules/book/src/Form/BookAdminEditForm.php b/core/modules/book/src/Form/BookAdminEditForm.php
index 8ec9d64a16..643a6c39f1 100644
--- a/core/modules/book/src/Form/BookAdminEditForm.php
+++ b/core/modules/book/src/Form/BookAdminEditForm.php
@@ -223,6 +223,8 @@ protected function bookAdminTableTree(array $tree, array &$form) {
 
       $form[$id]['title'] = [
         '#prefix' => !empty($indentation) ? \Drupal::service('renderer')->render($indentation) : '',
+        '#title' => $this->t('Title'),
+        '#title_display' => 'invisible',
         '#type' => 'textfield',
         '#default_value' => $data['link']['title'],
         '#maxlength' => 255,
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index bba1dd38c5..f844ba31eb 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -138,6 +138,8 @@ function _content_translation_form_language_content_settings_form_alter(array &$
         foreach ($fields as $field_name => $definition) {
           if ($definition->isComputed() || (!empty($storage_definitions[$field_name]) && _content_translation_is_field_translatability_configurable($entity_type, $storage_definitions[$field_name]))) {
             $form['settings'][$entity_type_id][$bundle]['fields'][$field_name] = [
+              '#title' => $definition->getLabel(),
+              // @todo Remove this?
               '#label' => $definition->getLabel(),
               '#type' => 'checkbox',
               '#default_value' => $definition->isTranslatable(),
@@ -153,6 +155,8 @@ function _content_translation_form_language_content_settings_form_alter(array &$
           // Only show the checkbox to enable translation if the bundles in the
           // entity might have fields and if there are fields to translate.
           $form['settings'][$entity_type_id][$bundle]['translatable'] = [
+            '#title' => t('Translatable'),
+            '#title_display' => 'invisible',
             '#type' => 'checkbox',
             '#default_value' => $content_translation_manager->isEnabled($entity_type_id, $bundle),
           ];
diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
index 2a4ffcd297..9d7740308f 100644
--- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
+++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeDefaultWidget.php
@@ -59,14 +59,16 @@ public static function create(ContainerInterface $container, array $configuratio
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
     $element = parent::formElement($items, $delta, $element, $form, $form_state);
 
+    $element['value']['#title'] = $this->fieldDefinition->getLabel();
+
     // If the field is date-only, make sure the title is displayed. Otherwise,
     // wrap everything in a fieldset, and the title will be shown in the legend.
     if ($this->getFieldSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) {
-      $element['value']['#title'] = $this->fieldDefinition->getLabel();
       $element['value']['#description'] = $this->fieldDefinition->getDescription();
     }
     else {
       $element['#theme_wrappers'][] = 'fieldset';
+      $element['value']['#title_display'] = 'invisible';
     }
 
     // Identify the type of date and time elements to use.
diff --git a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
index ebdbaed2c7..aa78177f5f 100644
--- a/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
+++ b/core/modules/field_ui/src/Form/EntityDisplayFormBase.php
@@ -426,9 +426,10 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, arr
         if (!empty($settings_form) || !empty($third_party_settings_form)) {
           $field_row['settings_edit'] = $base_button + [
             '#type' => 'image_button',
+            '#title' => $this->t('Edit'),
             '#name' => $field_name . '_settings_edit',
             '#src' => 'core/misc/icons/787878/cog.svg',
-            '#attributes' => ['class' => ['field-plugin-settings-edit'], 'alt' => $this->t('Edit')],
+            '#attributes' => ['class' => ['field-plugin-settings-edit']],
             '#op' => 'edit',
             // Do not check errors for the 'Edit' button, but make sure we get
             // the value of the 'plugin type' select.
diff --git a/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.module b/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.module
index 21b2272747..fcb14b76b4 100644
--- a/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.module
+++ b/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.module
@@ -40,6 +40,8 @@ function field_ui_test_form_entity_view_display_edit_form_alter(&$form, FormStat
     ],
     'weight' => [
       '#type' => 'textfield',
+      '#title' => 'Weight',
+      '#title_display' => 'invisible',
       '#default_value' => 0,
       '#size' => 3,
       '#attributes' => ['class' => ['field-weight']],
@@ -47,6 +49,8 @@ function field_ui_test_form_entity_view_display_edit_form_alter(&$form, FormStat
     'parent_wrapper' => [
       'parent' => [
         '#type' => 'select',
+        '#title' => 'Parent',
+        '#title_display' => 'invisible',
         '#options' => ['indent' => 'Indent'],
         '#empty_value' => '',
         '#default_value' => '',
diff --git a/core/modules/language/src/Element/LanguageConfiguration.php b/core/modules/language/src/Element/LanguageConfiguration.php
index 6920b0df01..89ef5f9272 100644
--- a/core/modules/language/src/Element/LanguageConfiguration.php
+++ b/core/modules/language/src/Element/LanguageConfiguration.php
@@ -34,7 +34,7 @@ public static function processLanguageConfiguration(&$element, FormStateInterfac
     $options = isset($element['#options']) ? $element['#options'] : [];
     // Avoid validation failure since we are moving the '#options' key in the
     // nested 'language' select element.
-    unset($element['#options']);
+    unset($element['#options'], $element['#type']);
     /** @var \Drupal\language\Entity\ContentLanguageSettings $default_config */
     $default_config = $element['#default_value'];
     $element['langcode'] = [
diff --git a/core/modules/language/src/Form/ContentLanguageSettingsForm.php b/core/modules/language/src/Form/ContentLanguageSettingsForm.php
index 5868d48faa..7cebca9785 100644
--- a/core/modules/language/src/Form/ContentLanguageSettingsForm.php
+++ b/core/modules/language/src/Form/ContentLanguageSettingsForm.php
@@ -118,7 +118,10 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       foreach ($bundles[$entity_type_id] as $bundle => $bundle_info) {
         $form['settings'][$entity_type_id][$bundle]['settings'] = [
           '#type' => 'item',
+          // @todo Remove this?
           '#label' => $bundle_info['label'],
+          '#title' => $bundle_info['label'],
+          '#title_display' => 'invisible',
           'language' => [
             '#type' => 'language_configuration',
             '#entity_information' => [
diff --git a/core/modules/node/src/Plugin/Search/NodeSearch.php b/core/modules/node/src/Plugin/Search/NodeSearch.php
index e4d5a0e7fc..f8a84d01c6 100644
--- a/core/modules/node/src/Plugin/Search/NodeSearch.php
+++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
@@ -822,7 +822,10 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       ];
       $form['content_ranking']['rankings'][$var]['value'] = [
         '#type' => 'select',
+        '#title' => $this->t("Influence of '@title'", ['@title' => $values['title']]),
+        '#title_display' => 'invisible',
         '#options' => $options,
+        // @todo Is this still necessary with the invisible title?
         '#attributes' => ['aria-label' => $this->t("Influence of '@title'", ['@title' => $values['title']])],
         '#default_value' => isset($this->configuration['rankings'][$var]) ? $this->configuration['rankings'][$var] : 0,
       ];
diff --git a/core/modules/system/tests/modules/entity_test/src/Plugin/Field/FieldWidget/ShapeOnlyColorEditableWidget.php b/core/modules/system/tests/modules/entity_test/src/Plugin/Field/FieldWidget/ShapeOnlyColorEditableWidget.php
index 6283bc3cea..6bba611dfd 100644
--- a/core/modules/system/tests/modules/entity_test/src/Plugin/Field/FieldWidget/ShapeOnlyColorEditableWidget.php
+++ b/core/modules/system/tests/modules/entity_test/src/Plugin/Field/FieldWidget/ShapeOnlyColorEditableWidget.php
@@ -30,6 +30,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
 
     $element['color'] = [
       '#type' => 'textfield',
+      '#title' => $this->t('Color'),
       '#default_value' => isset($items[$delta]->color) ? $items[$delta]->color : NULL,
       '#size' => 255,
     ];
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php
index a756dc50b6..fa842d456e 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestDisabledElementsForm.php
@@ -208,7 +208,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     // Buttons.
     $form['image_button'] = [
       '#type' => 'image_button',
-      '#value' => 'Image button',
+      '#title' => 'Image button',
       '#disabled' => TRUE,
     ];
     $form['button'] = [
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php
index 985a59c98c..bb146fada7 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestFileForm.php
@@ -25,6 +25,7 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state) {
     $form['file'] = [
       '#type' => 'file',
+      '#title' => $this->t('Test file'),
       '#multiple' => TRUE,
       '#attributes' => [
         'class' => ['cagatio'],
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestSelectForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestSelectForm.php
index d1b14d8d0e..934e83bf50 100644
--- a/core/modules/system/tests/modules/form_test/src/Form/FormTestSelectForm.php
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestSelectForm.php
@@ -119,6 +119,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['opt_groups'] = [
       '#type' => 'select',
+      '#title' => 'Opt groups',
       '#options' => [
         'optgroup_one' => ['one' => 'one', 'two' => 'two', 'three' => 'three', 'four' => '<strong>four</strong>'],
         'optgroup_two' => ['five' => 'five', 'six' => 'six'],
diff --git a/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php b/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php
index 91f3ec4a59..1b3423f9b0 100644
--- a/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php
+++ b/core/modules/system/tests/src/Functional/Form/ElementsLabelsTest.php
@@ -22,6 +22,9 @@ class ElementsLabelsTest extends BrowserTestBase {
   /**
    * Test form elements, labels, title attributes and required marks output
    * correctly and have the correct label option class if needed.
+   *
+   * @group legacy
+   * @expectedDeprecation Form elements must have a #title attribute as of Drupal 9.0.0. Form element "form_textfield_test_title_no_show" of #type "textfield" from form "form_label_test_form" is missing a #title attribute.
    */
   public function testFormLabels() {
     $this->drupalGet('form_test/form-labels');
@@ -99,6 +102,9 @@ public function testFormLabels() {
 
   /**
    * Tests XSS-protection of element labels.
+   *
+   * @group legacy
+   * @expectedDeprecation Form elements must have a #title attribute as of Drupal 9.0.0. Form element "form_textfield_test_title_no_show" of #type "textfield" from form "form_label_test_form" is missing a #title attribute.
    */
   public function testTitleEscaping() {
     $this->drupalGet('form_test/form-labels');
diff --git a/core/modules/system/tests/src/Functional/Form/FormTest.php b/core/modules/system/tests/src/Functional/Form/FormTest.php
index 849944b0f5..c8915a5df0 100644
--- a/core/modules/system/tests/src/Functional/Form/FormTest.php
+++ b/core/modules/system/tests/src/Functional/Form/FormTest.php
@@ -323,6 +323,9 @@ public function testGetFormsCsrfToken() {
    * messages.
    *
    * @see \Drupal\form_test\Form\FormTestValidateRequiredNoTitleForm
+   *
+   * @group legacy
+   * @expectedDeprecation Form elements must have a #title attribute as of Drupal 9.0.0. Form element "textfield" of #type "textfield" from form "form_test_validate_required_form_no_title" is missing a #title attribute.
    */
   public function testRequiredTextfieldNoTitle() {
     // Attempt to submit the form with no required field set.
diff --git a/core/modules/system/tests/src/Kernel/Form/FormElementMaxlengthTest.php b/core/modules/system/tests/src/Kernel/Form/FormElementMaxlengthTest.php
index 94026b6541..e071f96153 100644
--- a/core/modules/system/tests/src/Kernel/Form/FormElementMaxlengthTest.php
+++ b/core/modules/system/tests/src/Kernel/Form/FormElementMaxlengthTest.php
@@ -33,11 +33,13 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state) {
     $form['title'] = [
       '#type' => 'textfield',
+      '#title' => 'Title',
       '#maxlength' => 255,
     ];
 
     $form['description'] = [
       '#type' => 'textarea',
+      '#title' => 'Description',
       '#maxlength' => 255,
     ];
 
diff --git a/core/modules/views/src/Plugin/views/display/Block.php b/core/modules/views/src/Plugin/views/display/Block.php
index e210ee3231..c280a6df63 100644
--- a/core/modules/views/src/Plugin/views/display/Block.php
+++ b/core/modules/views/src/Plugin/views/display/Block.php
@@ -203,6 +203,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         $form['#title'] .= $this->t('Block category');
         $form['block_category'] = [
           '#type' => 'textfield',
+          '#title' => $this->t('Block category'),
+          '#title_display' => 'invisible',
           '#autocomplete_route_name' => 'block.category_autocomplete',
           '#description' => $this->t('The category this block will appear under on the <a href=":href">blocks placement page</a>.', [':href' => \Drupal::url('block.admin_display')]),
           '#default_value' => $this->getOption('block_category'),
@@ -237,6 +239,8 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         $allow = array_filter($this->getOption('allow'));
         $form['allow'] = [
           '#type' => 'checkboxes',
+          '#title' => $this->t('Allow settings in the block configuration'),
+          '#title_display' => 'invisible',
           '#default_value' => $allow,
           '#options' => $options,
         ];
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index 8821ea85a4..cb7a92a81e 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -862,7 +862,7 @@ public function buildExposedForm(&$form, FormStateInterface $form_state) {
       $form[$value] = $form['value'];
 
       if (isset($form[$value]['#title']) && !empty($form[$value]['#type']) && $form[$value]['#type'] != 'checkbox') {
-        unset($form[$value]['#title']);
+        $form[$value]['#title_display'] = 'invisible';
       }
 
       $this->exposedTranslate($form[$value], 'value');
@@ -1069,10 +1069,10 @@ protected function buildExposedFiltersGroupForm(&$form, FormStateInterface $form
         ],
         'operator' => $row['operator'],
         'value' => $row['value'],
-        // No title is given here, since this input is never displayed. It is
-        // only triggered by JavaScript.
         'remove' => [
           '#type' => 'checkbox',
+          '#title' => $this->t('Remove'),
+          '#title_display' => 'invisible',
           '#id' => 'views-removed-' . $item_id,
           '#attributes' => ['class' => ['views-remove-checkbox']],
           '#default_value' => 0,
@@ -1090,6 +1090,8 @@ protected function buildExposedFiltersGroupForm(&$form, FormStateInterface $form
     // From all groups, let chose which is the default.
     $form['group_info']['default_group'] = [
       '#type' => 'radios',
+      '#title' => $this->t('Default group'),
+      '#title_display' => 'invisible',
       '#options' => $groups,
       '#default_value' => $this->options['group_info']['default_group'],
       '#required' => TRUE,
@@ -1100,6 +1102,8 @@ protected function buildExposedFiltersGroupForm(&$form, FormStateInterface $form
     // From all groups, let chose which is the default.
     $form['group_info']['default_group_multiple'] = [
       '#type' => 'checkboxes',
+      '#title' => $this->t('Default group (multiple)'),
+      '#title_display' => 'invisible',
       '#options' => $groups,
       '#default_value' => $this->options['group_info']['default_group_multiple'],
       '#attributes' => [
diff --git a/core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php b/core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php
index ccabd268e0..01b47860e2 100644
--- a/core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php
@@ -67,6 +67,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     // Element without specifying the default value.
     $form['simple_datetime_element'] = [
       '#type' => 'datetime',
+      '#title' => 'datelist test, no default',
       '#date_date_format' => ['Y-m-d'],
       '#date_time_format' => ['H:i:s'],
       '#date_date_element' => 'HTML Date',
diff --git a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
index dc121eaf56..e3d872b96f 100644
--- a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php
@@ -96,10 +96,12 @@ public function getFormId() {
   public function buildForm(array $form, FormStateInterface $form_state) {
     $form['single'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single',
       '#target_type' => 'entity_test',
     ];
     $form['single_autocreate'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single autocreate',
       '#target_type' => 'entity_test',
       '#autocreate' => [
         'bundle' => 'entity_test',
@@ -107,6 +109,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     ];
     $form['single_autocreate_specific_uid'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single autocreate (specific UID)',
       '#target_type' => 'entity_test',
       '#autocreate' => [
         'bundle' => 'entity_test',
@@ -116,11 +119,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['tags'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Tags',
       '#target_type' => 'entity_test',
       '#tags' => TRUE,
     ];
     $form['tags_autocreate'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Tags autocreate',
       '#target_type' => 'entity_test',
       '#tags' => TRUE,
       '#autocreate' => [
@@ -129,6 +134,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     ];
     $form['tags_autocreate_specific_uid'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Tags autocreate (specific UID)',
       '#target_type' => 'entity_test',
       '#tags' => TRUE,
       '#autocreate' => [
@@ -139,11 +145,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['single_no_validate'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single (no validate)',
       '#target_type' => 'entity_test',
       '#validate_reference' => FALSE,
     ];
     $form['single_autocreate_no_validate'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single autocreate (no validate)',
       '#target_type' => 'entity_test',
       '#validate_reference' => FALSE,
       '#autocreate' => [
@@ -153,11 +161,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['single_access'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single access',
       '#target_type' => 'entity_test',
       '#default_value' => $this->referencedEntities[0],
     ];
     $form['tags_access'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Tags access',
       '#target_type' => 'entity_test',
       '#tags' => TRUE,
       '#default_value' => [$this->referencedEntities[0], $this->referencedEntities[1]],
@@ -165,10 +175,12 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['single_string_id'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Single (string ID)',
       '#target_type' => 'entity_test_string_id',
     ];
     $form['tags_string_id'] = [
       '#type' => 'entity_autocomplete',
+      '#title' => 'Tags (string ID)',
       '#target_type' => 'entity_test_string_id',
       '#tags' => TRUE,
     ];
diff --git a/core/tests/Drupal/Tests/Core/Form/fixtures/form_base_test.inc b/core/tests/Drupal/Tests/Core/Form/fixtures/form_base_test.inc
index b7623f7685..4f36ee0b0e 100644
--- a/core/tests/Drupal/Tests/Core/Form/fixtures/form_base_test.inc
+++ b/core/tests/Drupal/Tests/Core/Form/fixtures/form_base_test.inc
@@ -18,6 +18,7 @@ function test_form_id() {
   ];
   $form['options'] = [
     '#type' => 'radios',
+    '#title' => 'Options',
     '#options' => [
       'foo' => 'foo',
       'bar' => 'bar',
