diff --git a/core/modules/node/tests/src/Functional/NodeEditFormTest.php b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
index ce032e5..cc9ea5c 100644
--- a/core/modules/node/tests/src/Functional/NodeEditFormTest.php
+++ b/core/modules/node/tests/src/Functional/NodeEditFormTest.php
@@ -55,6 +55,7 @@ protected function setUp() {
    */
   public function testNodeEdit() {
     $this->drupalLogin($this->webUser);
+    $web_assert = $this->assertSession();
 
     $title_key = 'title[0][value]';
     $body_key = 'body[0][value]';
@@ -123,13 +124,16 @@ public function testNodeEdit() {
     // This invalid date will trigger an error.
     $edit['created[0][value][date]'] = $this->randomMachineName(8);
     // Get the current amount of open details elements.
-    $open_details_elements = count($this->cssSelect('details[open="open"]'));
+    $open_details_count = count($this->cssSelect('details[open="open"]'));
     $this->drupalPostForm(NULL, $edit, t('Save'));
-    // The node author details must be open.
-    $this->assertRaw('<details class="node-form-author js-form-wrapper form-wrapper" data-drupal-selector="edit-author" id="edit-author" open="open">');
+    // The node author details must be open and have child error attributes.
+    $this->assertRaw('<details class="node-form-author js-form-wrapper form-wrapper details--child-error form-wrapper--child-error" data-drupal-selector="edit-author" id="edit-author" open="open" data-child-error-count="3">');
+    $open_details = $this->cssSelect('details[open="open"]');
     // Only one extra details element should now be open.
-    $open_details_elements++;
-    $this->assertEqual(count($this->cssSelect('details[open="open"]')), $open_details_elements, 'Exactly one extra open &lt;details&gt; element found.');
+    $open_details_count++;
+    $this->assertEqual(count($open_details), $open_details_count, 'Exactly one extra open &lt;details&gt; element found.');
+    // The details summary should indicate the amount of child element errors.
+    $web_assert->elementTextContains('css', 'details.node-form-author .child-error-indicator', '(contains 3 errors)');
 
     // Edit the same node, save it and verify it's unpublished after unchecking
     // the 'Published' boolean_checkbox and clicking 'Save'.
diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml
index 2250a0b..46d14e8 100644
--- a/core/modules/system/tests/modules/form_test/form_test.routing.yml
+++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml
@@ -459,6 +459,14 @@ form_test.group_vertical_tabs:
   requirements:
     _access: 'TRUE'
 
+form_test.child_error_vertical_tabs:
+  path: '/form-test/child-error-vertical-tabs'
+  defaults:
+    _form: '\Drupal\form_test\Form\FormTestChildErrorVerticalTabsForm'
+    _title: 'Child element error vertical tabs testing'
+  requirements:
+    _access: 'TRUE'
+
 form_test.two_instances:
   path: '/form-test/two-instances-of-same-form'
   defaults:
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestChildErrorVerticalTabsForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestChildErrorVerticalTabsForm.php
new file mode 100644
index 0000000..7de7d01
--- /dev/null
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestChildErrorVerticalTabsForm.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\form_test\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Builds a form to test child element errors on #type 'vertical_tabs'.
+ */
+class FormTestChildErrorVerticalTabsForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'form_test_group_vertical_tabs';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['vertical_tabs'] = [
+      '#type' => 'vertical_tabs',
+    ];
+    $form['meta'] = [
+      '#type' => 'details',
+      '#title' => 'First group element',
+      '#group' => 'vertical_tabs',
+    ];
+    $form['meta']['element'] = [
+      '#type' => 'textfield',
+      '#title' => 'First nested element in details element',
+      '#required' => TRUE,
+    ];
+    $form['submit'] = [
+      '#type' => 'submit',
+      '#value' => 'Submit',
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+  }
+
+}
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/Core/Render/Element/VerticalTabsTest.php b/core/tests/Drupal/FunctionalJavascriptTests/Core/Render/Element/VerticalTabsTest.php
new file mode 100644
index 0000000..4677015
--- /dev/null
+++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Render/Element/VerticalTabsTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\FunctionalJavascriptTests\Core\Render\Element;
+
+use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
+
+/**
+ * Tests that sessions don't expire.
+ *
+ * @group Render
+ */
+class VerticalTabsTest extends JavascriptTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['form_test'];
+
+  /**
+   * Tests that a child error is indicated on a vertical tab.
+   */
+  public function testChildError() {
+    $web_assert = $this->assertSession();
+
+    $this->drupalGet('form-test/child-error-vertical-tabs');
+
+    $this->submitForm([], 'Submit');
+
+    $web_assert->elementTextContains('css', '.vertical-tabs__menu-item-title .child-error-indicator', '(contains an error)');
+  }
+
+}
