diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module
index f6aa3b4394ccc6db8fa03d278ca50df98202e27d..f0c8186d9da9710b7571087b5548ec55e98306ec 100644
--- a/core/modules/media_library/media_library.module
+++ b/core/modules/media_library/media_library.module
@@ -70,7 +70,21 @@ function media_library_views_post_render(ViewExecutable $view, &$output, CachePl
   if ($view->id() === 'media_library') {
     $output['#attached']['library'][] = 'media_library/view';
     if (strpos($view->current_display, 'widget') === 0) {
-      $query = MediaLibraryState::fromRequest($view->getRequest())->all();
+      try {
+        $query = MediaLibraryState::fromRequest($view->getRequest())->all();
+      }
+      catch (InvalidArgumentException $e) {
+        // MediaLibraryState::fromRequest() will throw an exception if the view
+        // is being previewed, since not all required query parameters will be
+        // present. In a preview, however, this can be omitted since we're
+        // merely previewing.
+        // @todo Use the views API for checking for the preview mode when it
+        //   lands. https://www.drupal.org/project/drupal/issues/3060855
+        if (empty($view->preview) && empty($view->live_preview)) {
+          throw $e;
+        }
+      }
+
       // If the current query contains any parameters we use to contextually
       // filter the view, ensure they persist across AJAX rebuilds.
       // The ajax_path is shared for all AJAX views on the page, but our query
diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
index 8667844e80e715b2a8efcd3b5e0e1f7629463767..9d54f6a43ab6054633bbe179b94f41d1b9b5ca40 100644
--- a/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
+++ b/core/modules/media_library/tests/src/FunctionalJavascript/MediaLibraryTest.php
@@ -26,7 +26,13 @@ class MediaLibraryTest extends WebDriverTestBase {
   /**
    * {@inheritdoc}
    */
-  protected static $modules = ['block', 'media_library_test', 'field_ui'];
+  protected static $modules = [
+    'block',
+    'media_library_test',
+    'field_ui',
+    'views',
+    'views_ui',
+  ];
 
   /**
    * {@inheritdoc}
@@ -73,6 +79,7 @@ protected function setUp() {
       'delete any media',
       'view media',
       'administer node form display',
+      'administer views',
     ]);
     $this->drupalLogin($user);
     $this->drupalPlaceBlock('local_tasks_block');
@@ -272,6 +279,43 @@ public function testWidgetWithoutMediaTypes() {
     $assert_session->elementNotExists('css', '.media-library-open-button[name^="field_null_types_media"]');
   }
 
+  /**
+   * Tests that the integration with Views works correctly.
+   */
+  public function testViewsAdmin() {
+    $assert_session = $this->assertSession();
+    $page = $this->getSession()->getPage();
+
+    // Assert that the widget can be seen and that there are 8 items.
+    $this->drupalGet('/admin/structure/views/view/media_library/edit/widget');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementsCount('css', '.media-library-item', 8);
+
+    // Assert that filtering works in live preview.
+    $page->find('css', '.media-library-view .view-filters')->fillField('name', 'snake');
+    $page->find('css', '.media-library-view .view-filters')->pressButton('Apply filters');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementsCount('css', '.media-library-item', 1);
+
+    // Test the same routine but in the view for the table wiget.
+    $this->drupalGet('/admin/structure/views/view/media_library/edit/widget_table');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementsCount('css', '.media-library-item', 8);
+
+    // Assert that filtering works in live preview.
+    $page->find('css', '.media-library-view .view-filters')->fillField('name', 'snake');
+    $page->find('css', '.media-library-view .view-filters')->pressButton('Apply filters');
+    $assert_session->assertWaitOnAjaxRequest();
+    $assert_session->elementsCount('css', '.media-library-item', 1);
+
+    // We cannot test clicking the 'Insert selected' button in either view
+    // because we expect an AJAX error, which would always throw an exception
+    // on ::tearDown even if we try to catch it here. If there is an API for
+    // marking certain elements 'unsuitable for previewing', we could test that
+    // here.
+    // @see https://www.drupal.org/project/drupal/issues/3060852
+  }
+
   /**
    * Tests that the widget access works as expected.
    */