diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
index 0121dcd6bd5fcdaba6ad9fcb3d9094d91aa0c8bd..1d890c974d3a97230d4bf607343313fdea6c308c 100644
--- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
+++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php
@@ -21,8 +21,8 @@
 use Drupal\Core\Url;
 use Drupal\field_ui\FieldUI;
 use Drupal\media\Entity\Media;
-use Drupal\media_library\MediaLibraryUiBuilder;
 use Drupal\media_library\MediaLibraryState;
+use Drupal\media_library\MediaLibraryUiBuilder;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Validator\ConstraintViolationInterface;
 
@@ -321,6 +321,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       ],
     ];
 
+    if ($this->fieldDefinition->isRequired()) {
+      $element['#element_validate'][] = [static::class, 'validateRequired'];
+    }
+
     // When the list of allowed types in the field configuration is null,
     // ::getAllowedMediaTypeIdsSorted() returns all existing media types. When
     // the list of allowed types is an empty array, we show a message to users
@@ -940,4 +944,29 @@ protected static function setFieldState(array $element, FormStateInterface $form
     static::setWidgetState($element['#field_parents'], $element['#field_name'], $form_state, $field_state);
   }
 
+  /**
+   * Validates whether the widget is required and contains values.
+   *
+   * @param array $element
+   *   The form element.
+   * @param \Drupal\Core\Form\FormStateInterface $form_state
+   *   The form state.
+   * @param array $form
+   *   The form array.
+   */
+  public static function validateRequired(array $element, FormStateInterface $form_state, array $form) {
+    // If a remove button triggered submit, this validation isn't needed.
+    if (in_array([static::class, 'removeItem'], $form_state->getSubmitHandlers(), TRUE)) {
+      return;
+    }
+
+    $field_state = static::getFieldState($element, $form_state);
+    // Trigger error if the field is required and no media is present. Although
+    // the Form API's default validation would also catch this, the validation
+    // error message is too vague, so a more precise one is provided here.
+    if (count($field_state['items']) === 0) {
+      $form_state->setError($element, t('@name field is required.', ['@name' => $element['#title']]));
+    }
+  }
+
 }
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php
index 5bfad98b6bc07ab4e406ff6a195d62c47d36985a..53400620ec168d60ab292b0fee2cb09feb5fd3ef 100644
--- a/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/EntityReferenceWidgetTest.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\Tests\media_library\FunctionalJavascript;
 
+use Drupal\field\Entity\FieldConfig;
+
 /**
  * Tests the Media library entity reference widget.
  *
@@ -448,4 +450,34 @@ public function testWidget() {
     $assert_session->pageTextNotContains('Snake');
   }
 
+  /**
+   * Tests saving a required media library field.
+   */
+  public function testRequiredMediaField() {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Make field_unlimited_media required.
+    $field_config = FieldConfig::loadByName('node', 'basic_page', 'field_unlimited_media');
+    $field_config->setRequired(TRUE)->save();
+
+    $this->drupalGet('node/add/basic_page');
+
+    $page->fillField('Title', 'My page');
+    $page->pressButton('Save');
+
+    // Check that a clear error message is shown.
+    $assert_session->pageTextNotContains('This value should not be null.');
+    $assert_session->pageTextContains(sprintf('%s field is required.', $field_config->label()));
+
+    // Open the media library, select an item and save the node.
+    $this->openMediaLibraryForField('field_unlimited_media');
+    $this->selectMediaItem(0);
+    $this->pressInsertSelected('Added one media item.');
+    $page->pressButton('Save');
+
+    // Confirm that the node was created.
+    $this->assertSession()->pageTextContains('Basic page My page has been created.');
+  }
+
 }