diff --git a/src/Controller/BrowserController.php b/src/Controller/BrowserController.php
index 8844705957a2e5bafb583fc60e3d64489355d618..095561cd15efa01c8ee1fa1eeedb190eb4844788 100644
--- a/src/Controller/BrowserController.php
+++ b/src/Controller/BrowserController.php
@@ -78,6 +78,14 @@ class BrowserController extends ControllerBase {
       $active_plugins[$source->getPluginId()] = $source->getPluginDefinition()['label'];
     }
 
+    $pm_validation_errors = [];
+    $pm_validation_messages = [];
+    if ($ui_install_enabled) {
+      $pm_validate = $this->installReadiness->validatePackageManager();
+      $pm_validation_errors = $pm_validate['errors'];
+      $pm_validation_messages = $pm_validate['messages'];
+    }
+
     return [
       '#theme' => 'project_browser_main_app',
       '#attached' => [
@@ -101,7 +109,8 @@ class BrowserController extends ControllerBase {
             'current_sources_keys' => $current_sources_keys,
             'ui_install' => $ui_install_enabled,
             'stage_available' => $ui_install_enabled ? $this->installReadiness->installerAvailable() : FALSE,
-            'pm_validation' => $ui_install_enabled ? $this->installReadiness->validatePackageManager() : TRUE,
+            'pm_validation_errors' => count($pm_validation_errors) ? $pm_validation_errors : FALSE,
+            'pm_validation_messages' => count($pm_validation_messages) ? $pm_validation_messages : FALSE,
           ],
         ],
       ],
diff --git a/src/InstallReadiness.php b/src/InstallReadiness.php
index 687d842fe644a2346782bb1ec1b10795348a25b0..4c72e1584e692961e5205eb171c7528d603b9fcc 100644
--- a/src/InstallReadiness.php
+++ b/src/InstallReadiness.php
@@ -4,6 +4,7 @@ namespace Drupal\project_browser;
 
 use Drupal\package_manager\StatusCheckTrait;
 use Drupal\project_browser\ComposerInstaller\Installer;
+use Drupal\system\SystemManager;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
@@ -21,22 +22,32 @@ class InstallReadiness {
   /**
    * Checks if the environment meets Package Manager install requirements.
    *
-   * @return false|string
-   *   FALSE if no validation errors, otherwise an error message.
+   * @return array[]
+   *   errors - an array of messages with severity 2
+   *   messages - all other messages below severity 2 (warnings)
    */
   public function validatePackageManager() {
-    $text = '';
-    $results = $this->runStatusCheck($this->installer, $this->eventDispatcher);
-    foreach ($results as $result) {
+    $errors = [];
+    $warnings = [];
+    foreach ($this->runStatusCheck($this->installer, $this->eventDispatcher) as $result) {
       $messages = $result->messages;
       $summary = $result->summary;
-
       if ($summary) {
         array_unshift($messages, $summary);
       }
-      $text .= implode("\n", $messages) . "\n";
+      $text = implode("\n", $messages);
+
+      if ($result->severity == SystemManager::REQUIREMENT_ERROR) {
+        $errors[] = $text;
+      }
+      else {
+        $warnings[] = $text;
+      }
     }
-    return $text ?: FALSE;
+    return [
+      'errors' => $errors,
+      'messages' => $warnings,
+    ];
   }
 
   /**
diff --git a/sveltejs/public/build/bundle.css b/sveltejs/public/build/bundle.css
new file mode 100644
index 0000000000000000000000000000000000000000..1583d982fb62bd8395404706a8c59c89739f8b06
Binary files /dev/null and b/sveltejs/public/build/bundle.css differ
diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js
index 7b2eaee35b66b6ae05e15334a48ce9094d98b8e4..d04c3c57a46f7c5b6510a1914eab5d0492ae9dc7 100644
Binary files a/sveltejs/public/build/bundle.js and b/sveltejs/public/build/bundle.js differ
diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map
index 7f3df18de26eefb49d23d76e3536e2bfcc8f9046..bd094a77375f5f869ca32110ab563e96f203856d 100644
Binary files a/sveltejs/public/build/bundle.js.map and b/sveltejs/public/build/bundle.js.map differ
diff --git a/sveltejs/src/Project/ActionButton.svelte b/sveltejs/src/Project/ActionButton.svelte
index 0fa751253a15a9504a6215e42fbb520cb8f9201a..3786785ce7cc4fb736b16e5fb63b3028a12edbc5 100644
--- a/sveltejs/src/Project/ActionButton.svelte
+++ b/sveltejs/src/Project/ActionButton.svelte
@@ -4,7 +4,7 @@
     MODULE_STATUS,
     ORIGIN_URL,
     ALLOW_UI_INSTALL,
-    PM_VALIDATION_ERROR,
+    PM_VALIDATION_ERRORS,
   } from '../constants';
   import Loading from '../Loading.svelte';
   import { openPopup, getCommandsPopupMessage } from '../popup';
@@ -212,7 +212,7 @@
     </span>
   {:else}
     <span>
-      {#if !PM_VALIDATION_ERROR && ALLOW_UI_INSTALL}
+      {#if !PM_VALIDATION_ERRORS && ALLOW_UI_INSTALL}
         {#if loading}
           <span class="loading-ellipsis">{loadingPhase}</span>
           <Loading positionAbsolute={true} />
diff --git a/sveltejs/src/Project/AddInstallButton.svelte b/sveltejs/src/Project/AddInstallButton.svelte
index 0e2844cb512dd5754465ee748c4f6b83f76e427b..df63992199dc749c658d471559f9ec00a601fdcc 100644
--- a/sveltejs/src/Project/AddInstallButton.svelte
+++ b/sveltejs/src/Project/AddInstallButton.svelte
@@ -1,6 +1,10 @@
 <script>
   import { openPopup } from '../popup';
-  import { MODULE_STATUS, ORIGIN_URL, PM_VALIDATION_ERROR } from '../constants';
+  import {
+    MODULE_STATUS,
+    ORIGIN_URL,
+    PM_VALIDATION_ERRORS,
+  } from '../constants';
   import ProjectButtonBase from './ProjectButtonBase.svelte';
   import { isPackageManagerRequired } from '../stores';
 
@@ -162,7 +166,7 @@
       downloadModule(true);
     }
   }}
-  disabled={PM_VALIDATION_ERROR && $isPackageManagerRequired}
+  disabled={PM_VALIDATION_ERRORS && $isPackageManagerRequired}
 >
   {alreadyAdded ? Drupal.t('Install') : Drupal.t('Add and Install')}<span
     class="visually-hidden">{project.title}</span
diff --git a/sveltejs/src/ProjectBrowser.svelte b/sveltejs/src/ProjectBrowser.svelte
index 6ca1bfa2c66e912376d81959a724085f4836c0dd..76a037cc8787fc449ff5abfa971177f5934b09e6 100644
--- a/sveltejs/src/ProjectBrowser.svelte
+++ b/sveltejs/src/ProjectBrowser.svelte
@@ -33,7 +33,8 @@
     SORT_OPTIONS,
     MODULE_STATUS,
     ALLOW_UI_INSTALL,
-    PM_VALIDATION_ERROR,
+    PM_VALIDATION_ERRORS,
+    PM_VALIDATION_MESSAGES,
     ACTIVE_PLUGINS,
   } from './constants';
   // cspell:ignore tabwise
@@ -357,18 +358,38 @@
         {/if}
       </div>
 
-      <!-- If Package Manager is required and UI installs are enabled,but the
-           site configuration does not support them, display a message
-           informing the user what must be changed for UI installs to work. -->
-      {#if $isPackageManagerRequired && PM_VALIDATION_ERROR && typeof PM_VALIDATION_ERROR === 'string' && MODULE_STATUS.package_manager && ALLOW_UI_INSTALL}
-        <div class="project-browser__install-warning">
-          <p class="project-browser__warning-header">
-            <strong>{Drupal.t('Unable to download modules via the UI')}</strong>
-          </p>
-          <p class="project-browser__warning">
-            <em>{@html PM_VALIDATION_ERROR}</em>
-          </p>
-        </div>
+      <!-- If Package Manager is required and UI installs are enabled, validate
+           and print all messages, warnings and errors. If there were errors,
+           display a message informing the user what must be changed for UI
+           installs to work. -->
+      {#if $isPackageManagerRequired && ALLOW_UI_INSTALL && MODULE_STATUS.package_manager}
+        {#if PM_VALIDATION_ERRORS}
+          <div class="project-browser__install-warning severity-error">
+            <p class="project-browser__warning-header">
+              <strong
+                >{Drupal.t('Unable to download modules via the UI')}</strong
+              >
+            </p>
+            <p class="project-browser__warning">
+              <em>
+                {#each PM_VALIDATION_ERRORS as message}
+                  {@html message}<br />
+                {/each}
+              </em>
+            </p>
+          </div>
+        {/if}
+        {#if PM_VALIDATION_MESSAGES}
+          <div class="project-browser__install-warning">
+            <p class="project-browser__warning">
+              <em>
+                {#each PM_VALIDATION_MESSAGES as message}
+                  {@html message}<br />
+                {/each}
+              </em>
+            </p>
+          </div>
+        {/if}
       {/if}
       <Pagination
         page={$page}
diff --git a/sveltejs/src/constants.js b/sveltejs/src/constants.js
index 7f204cdd6651450b3b01c7034f0682cf510ee2dc..3efd14e1232e27727803ad6926fc05cf67f11727 100644
--- a/sveltejs/src/constants.js
+++ b/sveltejs/src/constants.js
@@ -21,5 +21,6 @@ export const ALLOW_UI_INSTALL = drupalSettings.project_browser.ui_install;
 export const DARK_COLOR_SCHEME =
   matchMedia('(forced-colors: active)').matches &&
   matchMedia('(prefers-color-scheme: dark)').matches;
-export const PM_VALIDATION_ERROR = drupalSettings.project_browser.pm_validation;
+export const PM_VALIDATION_ERRORS = drupalSettings.project_browser.pm_validation_errors;
+export const PM_VALIDATION_MESSAGES = drupalSettings.project_browser.pm_validation_messages;
 export const ACTIVE_PLUGINS = drupalSettings.project_browser.active_plugins;
diff --git a/tests/modules/project_browser_test/config/install/project_browser_test.settings.yml b/tests/modules/project_browser_test/config/install/project_browser_test.settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f8b10ea8b65113f95389c0d91297ea2add81e502
--- /dev/null
+++ b/tests/modules/project_browser_test/config/install/project_browser_test.settings.yml
@@ -0,0 +1,2 @@
+simulateError: false
+simulateWarning: false
diff --git a/tests/modules/project_browser_test/config/schema/project_browser_test.schema.yml b/tests/modules/project_browser_test/config/schema/project_browser_test.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..46ae85ca419014ea361a5b579f2144c7a57311b9
--- /dev/null
+++ b/tests/modules/project_browser_test/config/schema/project_browser_test.schema.yml
@@ -0,0 +1,10 @@
+project_browser_test.settings:
+  type: config_object
+  label: 'Project Browser Test Settings'
+  mapping:
+    simulateError:
+      type: boolean
+      label: 'Simulate a package manager error'
+    simulateWarning:
+      type: boolean
+      label: 'Simulate a package manager warning'
diff --git a/tests/modules/project_browser_test/project_browser_test.services.yml b/tests/modules/project_browser_test/project_browser_test.services.yml
index e157cf9c84c9cd5c0e7f0c69d24f52e731f19db1..4e60b58c73cdde1f975a99643384055a72da329e 100644
--- a/tests/modules/project_browser_test/project_browser_test.services.yml
+++ b/tests/modules/project_browser_test/project_browser_test.services.yml
@@ -7,3 +7,11 @@ services:
     class: Drupal\project_browser_test\DrupalOrgClientMiddleware
     tags:
       - { name: http_client_middleware }
+
+  Drupal\project_browser_test\Validator\ProjectBrowserTestSimulateErrorValidator:
+    tags:
+      - { name: event_subscriber }
+
+  Drupal\project_browser_test\Validator\ProjectBrowserTestSimulateWarningValidator:
+    tags:
+      - { name: event_subscriber }
diff --git a/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateErrorValidator.php b/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateErrorValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..ecf42d376c75a6bce1291b85940df3aeca00fa9d
--- /dev/null
+++ b/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateErrorValidator.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\project_browser_test\Validator;
+
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Drupal\package_manager\Event\PreCreateEvent;
+use Drupal\package_manager\Event\PreOperationStageEvent;
+
+/**
+ * Simulates a package manager warning.
+ */
+final class ProjectBrowserTestSimulateErrorValidator implements EventSubscriberInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function simulateError(PreOperationStageEvent $event): void {
+    // Always throw an error when this is enabled.
+    if (!\Drupal::config('project_browser_test.settings')->get('simulateError')) {
+      return;
+    }
+    $event->addError([$this->t("Simulate an error message for the project browser.")]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents(): array {
+    return [
+      PreCreateEvent::class => 'simulateError',
+    ];
+  }
+
+}
diff --git a/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateWarningValidator.php b/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateWarningValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..c43c5a1702ced20aea695447095f45203ec3fad3
--- /dev/null
+++ b/tests/modules/project_browser_test/src/Validator/ProjectBrowserTestSimulateWarningValidator.php
@@ -0,0 +1,38 @@
+<?php
+
+declare(strict_types = 1);
+
+namespace Drupal\project_browser_test\Validator;
+
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\package_manager\Event\StatusCheckEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Simulates a package manager warning.
+ */
+final class ProjectBrowserTestSimulateWarningValidator implements EventSubscriberInterface {
+
+  use StringTranslationTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function simulateWarning(StatusCheckEvent $event): void {
+    if (!\Drupal::config('project_browser_test.settings')->get('simulateWarning')) {
+      return;
+    }
+    // Always throw an error when this is enabled.
+    $event->addWarning([$this->t("Simulate a warning message for the project browser.")]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents(): array {
+    return [
+      StatusCheckEvent::class => 'simulateError',
+    ];
+  }
+
+}
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
index aeded65d7d15aa5b6e16a8eb90a7040449a57c78..fe46e18f7b55af780cea55cb2b0cc32f21d293ab 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
@@ -199,4 +199,46 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
 
   }
 
+  /**
+   * Confirm that a status check error prevents download and install.
+   */
+  public function testPackageManagerErrorPreventsDownload(): void {
+    \Drupal::configFactory()
+      ->getEditable('project_browser_test.settings')
+      ->set('simulateError', TRUE)
+      ->save(TRUE);
+
+    $assert_session = $this->assertSession();
+    $this->drupalGet('admin/modules/browse');
+    $this->assertSession()->pageTextContains("Simulate an error message for the project browser.");
+    $this->svelteInitHelper('text', 'Cream cheese on a bagel');
+    $cream_cheese_module_selector = '#project-browser .project-browser__main ul > li:nth-child(1)';
+    $download_button = $assert_session->waitForElementVisible('css', "$cream_cheese_module_selector button");
+    $this->assertNotEmpty($download_button);
+    $this->assertSame('View Commands for Cream cheese on a bagel', $download_button->getText());
+  }
+
+  /**
+   * Confirm that a status check warning allows download and install.
+   */
+  public function testPackageManagerWarningAllowsDownloadInstall(): void {
+    \Drupal::configFactory()
+      ->getEditable('project_browser_test.settings')
+      ->set('simulateWarning', TRUE)
+      ->save(TRUE);
+
+    $assert_session = $this->assertSession();
+    $this->drupalGet('admin/modules/browse');
+    $this->assertSession()->pageTextContains("Simulate a warning message for the project browser.");
+    $this->svelteInitHelper('text', 'Cream cheese on a bagel');
+    $cream_cheese_module_selector = '#project-browser .project-browser__main ul > li:nth-child(1)';
+    $download_button = $assert_session->waitForElementVisible('css', "$cream_cheese_module_selector button");
+    $this->assertNotEmpty($download_button);
+    $this->assertSame('Add and Install Cream cheese on a bagel', $download_button->getText());
+    $download_button->click();
+    $installed_action = $assert_session->waitForElementVisible('css', "$cream_cheese_module_selector .project_status-indicator");
+    $assert_session->waitForText('✓ Cream cheese on a bagel is Installed');
+    $this->assertSame('✓ Cream cheese on a bagel is Installed', $installed_action->getText());
+  }
+
 }