diff --git a/dictionary.txt b/dictionary.txt
index ad242b1dbe48ca398515a0c4b87d280b1344c546..0ccd8f9ed65c2dcaf8afee687cee4548d3000289 100644
--- a/dictionary.txt
+++ b/dictionary.txt
@@ -11,3 +11,4 @@ filedate
 unshallow
 hhvm
 tmpdir
+proc_open
diff --git a/package_manager/package_manager.module b/package_manager/package_manager.module
index 55ca66e5d1aa144f392ec7072e7d1a71dbe0571f..4847f83dbced52fc17606f19473c8e11a7617418 100644
--- a/package_manager/package_manager.module
+++ b/package_manager/package_manager.module
@@ -51,6 +51,9 @@ function package_manager_help($route_name, RouteMatchInterface $route_match) {
       $output .= '<h3 id="package-manager-faq">' . t('FAQ') . '</h3>';
       $output .= '<h4 id="package-manager-composer-related-faq">' . t('FAQs related to Composer') . '</h4>';
       $output .= '<ul>';
+      $output .= '  <li>' . t('What if it says the <code>proc_open()</code> function is disabled on your PHP installation?');
+      $output .= '    <p>' . t('Ask your system administrator to remove <code>proc_open()</code> from the <a href=":url">disable_functions</a> setting in <code>php.ini</code>.', [':url' => 'https://www.php.net/manual/en/ini.core.php#ini.disable-functions']) . '</p>';
+      $output .= '  </li>';
       $output .= '  <li>' . t('What if it says the <code>composer</code> executable cannot be found?');
       $output .= '    <p>' . t("If the <code>composer</code> executable's path cannot be automatically determined, it can be explicitly set by adding the following line to <code>settings.php</code>:") . '</p>';
       $output .= "    <pre><code>\$config['package_manager.settings']['executables']['composer'] = '/full/path/to/composer.phar';</code></pre>";
diff --git a/package_manager/src/Validator/ComposerValidator.php b/package_manager/src/Validator/ComposerValidator.php
index e4aa6ced612943e75ca5bafcfd58648fd014254b..bb686a457d32cda8d5de496f1a67c51606563255 100644
--- a/package_manager/src/Validator/ComposerValidator.php
+++ b/package_manager/src/Validator/ComposerValidator.php
@@ -46,6 +46,19 @@ final class ComposerValidator implements EventSubscriberInterface {
    * Validates that the Composer executable is the correct version.
    */
   public function validate(PreOperationStageEvent $event): void {
+    // If we can't stat processes, there's nothing else we can possibly do here.
+    // @see \Symfony\Component\Process\Process::__construct()
+    if (!\function_exists('proc_open')) {
+      $message = $this->t('Composer cannot be used because the <code>proc_open()</code> function is disabled.');
+      if ($this->moduleHandler->moduleExists('help')) {
+        $message = $this->t('@message See <a href=":package-manager-help">the help page</a> for information on how to resolve the problem.', [
+          ':package-manager-help' => self::getHelpUrl('package-manager-composer-related-faq'),
+        ]);
+      }
+      $event->addError([$message]);
+      return;
+    }
+
     $messages = [];
     $dir = $event instanceof PreApplyEvent
       ? $event->stage->getStageDirectory()