diff --git a/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php b/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php
index 600afe7dbde773a6052b129b10e4f322198ba95c..115479d19ddf2822f204a0bf2f256232bc9994f7 100644
--- a/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php
+++ b/automatic_updates_extensions/src/Validator/UpdateReleaseValidator.php
@@ -6,6 +6,7 @@ use Drupal\automatic_updates\ProjectInfo;
 use Drupal\automatic_updates_extensions\ExtensionUpdater;
 use Drupal\automatic_updates\LegacyVersionUtility;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
@@ -20,6 +21,83 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
 
   use StringTranslationTrait;
 
+  /**
+   * Checks if the given version of a project is supported.
+   *
+   * Checks if the given version of the given project is in the core update
+   * system's list of known, secure, installable releases of that project.
+   * considered a supported release by verifying if the project is found in the
+   * core update system's list of known, secure, and installable releases.
+   *
+   * @param string $name
+   *   The name of the project.
+   * @param string $semantic_version
+   *   A semantic version number for the project.
+   *
+   * @return bool
+   *   TRUE if the given version of the project is supported, otherwise FALSE.
+   *   given version is not supported will return FALSE.
+   */
+  protected function isSupportedRelease(string $name, string $semantic_version): bool {
+    $supported_releases = (new ProjectInfo($name))->getInstallableReleases();
+    if (!$supported_releases) {
+      return FALSE;
+    }
+
+    // If this version is found in the list of installable releases, it is
+    // secured and supported.
+    if (array_key_exists($semantic_version, $supported_releases)) {
+      return TRUE;
+    }
+    // If the semantic version number wasn't in the list of
+    // installable releases, convert it to a legacy version number and see
+    // if the version number is in the list.
+    $legacy_version = LegacyVersionUtility::convertToLegacyVersion($semantic_version);
+    if ($legacy_version && array_key_exists($legacy_version, $supported_releases)) {
+      return TRUE;
+    }
+    // Neither the semantic version nor the legacy version are in the list
+    // of installable releases, so the release isn't supported.
+    return FALSE;
+  }
+
+  /**
+   * Checks that the packages are secure and supported.
+   *
+   * @param \Drupal\package_manager\Event\PreApplyEvent $event
+   *   The event object.
+   */
+  public function checkStagedReleases(PreApplyEvent $event): void {
+    $messages = [];
+
+    // Get packages that were installed and also updated in the staging area.
+    $active = $event->getStage()->getActiveComposer();
+    $staged = $event->getStage()->getStageComposer();
+    $updated_packages = $staged->getPackagesWithDifferentVersionsIn($active);
+    foreach ($updated_packages as $staged_package) {
+      if (!in_array($staged_package->getType(),
+        ['drupal-module', 'drupal-theme'], TRUE)) {
+        continue;
+      }
+      [, $project_name] = explode('/', $staged_package->getName());
+      $semantic_version = $staged_package->getPrettyVersion();
+      if (!$this->isSupportedRelease($project_name, $semantic_version)) {
+        $messages[] = $this->t('Project @project_name to version @version', [
+          '@project_name' => $project_name,
+          '@version' => $semantic_version,
+        ]);
+      }
+    }
+    if ($messages) {
+      $summary = $this->formatPlural(
+        count($messages),
+        'Cannot update because the following project version is not in the list of installable releases.',
+        'Cannot update because the following project versions are not in the list of installable releases.'
+      );
+      $event->addError($messages, $summary);
+    }
+  }
+
   /**
    * Checks that the update projects are secure and supported.
    *
@@ -41,33 +119,12 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
         $project_name = $package_parts[1];
         // If the version isn't in the list of installable releases, then it
         // isn't secure and supported and the user should receive an error.
-        $releases = (new ProjectInfo($project_name))->getInstallableReleases();
-        $is_missing_version = FALSE;
-        if (empty($releases)) {
-          $is_missing_version = TRUE;
-        }
-        elseif (!array_key_exists($sematic_version, $releases)) {
-          $legacy_version = LegacyVersionUtility::convertToLegacyVersion($sematic_version);
-          if ($legacy_version) {
-            if (!array_key_exists($legacy_version, $releases)) {
-              // If we cannot find the version using semantic or legacy then the
-              // version is missing.
-              $is_missing_version = TRUE;
-            }
-          }
-          else {
-            // If we cannot convert the semantic version into a legacy version
-            // then the version is missing.
-            $is_missing_version = TRUE;
-          }
-        }
-        if ($is_missing_version) {
+        if (!$this->isSupportedRelease($project_name, $sematic_version)) {
           $messages[] = $this->t('Project @project_name to version @version', [
             '@project_name' => $project_name,
             '@version' => $sematic_version,
           ]);
         }
-
       }
     }
     if ($messages) {
@@ -86,6 +143,7 @@ final class UpdateReleaseValidator implements EventSubscriberInterface {
   public static function getSubscribedEvents() {
     return [
       PreCreateEvent::class => 'checkRelease',
+      PreApplyEvent::class => 'checkStagedReleases',
     ];
   }
 
diff --git a/automatic_updates_extensions/tests/fixtures/update_release_validator/active.installed.json b/automatic_updates_extensions/tests/fixtures/update_release_validator/active.installed.json
new file mode 100644
index 0000000000000000000000000000000000000000..4e077b457077d987dbbfdc465ca7ba5cf56f9454
--- /dev/null
+++ b/automatic_updates_extensions/tests/fixtures/update_release_validator/active.installed.json
@@ -0,0 +1,35 @@
+{
+    "packages": [
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+          "name": "drupal/dependency",
+          "version": "9.8.0",
+          "type": "drupal-library"
+        },
+        {
+          "name": "drupal/aaa_automatic_updates_test",
+          "version": "7.0.0",
+          "type": "drupal-module"
+        },
+        {
+          "name": "drupal/aaa_update_test",
+          "version": "2.0.0",
+          "type": "drupal-module"
+        },
+        {
+          "name": "drupal/semver_test",
+          "version": "8.1.0",
+          "type": "drupal-module"
+        }
+    ]
+}
diff --git a/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_supported_update.staged.installed.json b/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_supported_update.staged.installed.json
new file mode 100644
index 0000000000000000000000000000000000000000..2738b13cd4c4473cefc4bbb92666a684b032ca38
--- /dev/null
+++ b/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_supported_update.staged.installed.json
@@ -0,0 +1,25 @@
+{
+    "packages": [
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+          "name": "drupal/dependency",
+          "version": "9.8.1",
+          "type": "drupal-library"
+        },
+        {
+          "name": "drupal/aaa_update_test",
+          "version": "2.1.0",
+          "type": "drupal-module"
+        }
+    ]
+}
diff --git a/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_unsupported_update.staged.installed.json b/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_unsupported_update.staged.installed.json
new file mode 100644
index 0000000000000000000000000000000000000000..d7ef4fbab2db1a0a2c19a56b80bdfe08d9243834
--- /dev/null
+++ b/automatic_updates_extensions/tests/fixtures/update_release_validator/legacy_unsupported_update.staged.installed.json
@@ -0,0 +1,25 @@
+{
+    "packages": [
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+          "name": "drupal/dependency",
+          "version": "9.8.1",
+          "type": "drupal-library"
+        },
+        {
+          "name": "drupal/aaa_update_test",
+          "version": "3.0.0",
+          "type": "drupal-module"
+        }
+    ]
+}
diff --git a/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_supported_update.staged.installed.json b/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_supported_update.staged.installed.json
new file mode 100644
index 0000000000000000000000000000000000000000..2ed8f728c71e4946e0ef6e8f8c365528a930793d
--- /dev/null
+++ b/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_supported_update.staged.installed.json
@@ -0,0 +1,25 @@
+{
+    "packages": [
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+          "name": "drupal/dependency",
+          "version": "9.8.1",
+          "type": "drupal-library"
+        },
+        {
+          "name": "drupal/semver_test",
+          "version": "8.1.1",
+          "type": "drupal-module"
+        }
+    ]
+}
diff --git a/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_unsupported_update.staged.installed.json b/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_unsupported_update.staged.installed.json
new file mode 100644
index 0000000000000000000000000000000000000000..0d4ca73efa51008ce73638238e45db7731bfbc0e
--- /dev/null
+++ b/automatic_updates_extensions/tests/fixtures/update_release_validator/semver_unsupported_update.staged.installed.json
@@ -0,0 +1,25 @@
+{
+    "packages": [
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+          "name": "drupal/dependency",
+          "version": "9.8.1",
+          "type": "drupal-library"
+        },
+        {
+          "name": "drupal/semver_test",
+          "version": "8.2.0",
+          "type": "drupal-module"
+        }
+    ]
+}
diff --git a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
index 1e7e9fd9ccd31ff3cd0c29cf0b8c5f40e6cf5182..ccb42646a28ade83dbd035f7740a41c45d464ed0 100644
--- a/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
+++ b/automatic_updates_extensions/tests/src/Functional/UpdaterFormTest.php
@@ -47,8 +47,8 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
    */
   public function providerSuccessfulUpdate() {
     return [
-      'maintiance_mode_on, semver' => [TRUE, 'semver_test', '8.1.0', '8.1.1'],
-      'maintiance_mode_off, legacy' => [FALSE, 'aaa_update_test', '8.x-2.0', '8.x-2.1'],
+      'maintenance mode on, semver' => [TRUE, 'semver_test', '8.1.0', '8.1.1'],
+      'maintenance mode off, legacy' => [FALSE, 'aaa_update_test', '8.x-2.0', '8.x-2.1'],
     ];
   }
 
@@ -140,10 +140,13 @@ class UpdaterFormTest extends AutomaticUpdatesFunctionalTestBase {
    * @dataProvider providerSuccessfulUpdate
    */
   public function testSuccessfulUpdate(bool $maintenance_mode_on, string $project_name, string $installed_version, string $target_version): void {
-    // Disable the scaffold file permissions validator because it will try to
-    // read composer.json from the staging area, which won't exist because
-    // Package Manager is bypassed.
-    $this->disableValidators(['automatic_updates.validator.scaffold_file_permissions']);
+    // Disable the scaffold file permissions and target release validators
+    // because they will try to read composer.json from the staging area,
+    // which won't exist because Package Manager is bypassed.
+    $this->disableValidators([
+      'automatic_updates.validator.scaffold_file_permissions',
+      'automatic_updates_extensions.validator.target_release',
+    ]);
 
     $this->container->get('theme_installer')->install(['automatic_updates_theme_with_updates']);
     $this->updateProject = $project_name;
diff --git a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
index 4b0714b0bbe88b60d7ba6b9107b67d70048d696e..f2d36d54133228ca9406b39781933d42f752c4ef 100644
--- a/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
+++ b/automatic_updates_extensions/tests/src/Kernel/Validator/UpdateReleaseValidatorTest.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\automatic_updates_extensions\Kernel\Validator;
 
 use Drupal\automatic_updates\LegacyVersionUtility;
+use Drupal\package_manager\Event\PreApplyEvent;
 use Drupal\package_manager\Event\PreCreateEvent;
 use Drupal\package_manager\ValidationResult;
 use Drupal\Tests\automatic_updates_extensions\Kernel\AutomaticUpdatesExtensionsKernelTestBase;
@@ -23,7 +24,22 @@ class UpdateReleaseValidatorTest extends AutomaticUpdatesExtensionsKernelTestBas
   }
 
   /**
-   * Tests updating to a release.
+   * Data provider for testPreCreateException().
+   *
+   * @return array[]
+   *   The test cases.
+   */
+  public function providerTestPreCreateException(): array {
+    return [
+      'semver, supported update' => ['semver_test', '8.1.0', '8.1.1', FALSE],
+      'semver, update to unsupported branch' => ['semver_test', '8.1.0', '8.2.0', TRUE],
+      'legacy, supported update' => ['aaa_update_test', '8.x-2.0', '8.x-2.1', FALSE],
+      'legacy, update to unsupported branch' => ['aaa_update_test', '8.x-2.0', '8.x-3.0', TRUE],
+    ];
+  }
+
+  /**
+   * Tests updating to a release during pre-create.
    *
    * @param string $project
    *   The project to update.
@@ -34,18 +50,21 @@ class UpdateReleaseValidatorTest extends AutomaticUpdatesExtensionsKernelTestBas
    * @param bool $error_expected
    *   Whether an error is expected in the update.
    *
-   * @dataProvider providerTestRelease
+   * @dataProvider providerTestPreCreateException
    */
-  public function testRelease(string $project, string $installed_version, string $target_version, bool $error_expected) {
+  public function testPreCreateException(string $project, string $installed_version, string $target_version, bool $error_expected): void {
     $this->enableModules([$project]);
+
     $module_info = ['version' => $installed_version, 'project' => $project];
     $this->config('update_test.settings')
       ->set("system_info.$project", $module_info)
       ->save();
+
     $this->setReleaseMetadataForProjects([
       $project => __DIR__ . "/../../../fixtures/release-history/$project.1.1.xml",
       'drupal' => __DIR__ . '/../../../../../tests/fixtures/release-history/drupal.9.8.2.xml',
     ]);
+
     if ($error_expected) {
       $expected_results = [
         ValidationResult::createError(
@@ -62,18 +81,90 @@ class UpdateReleaseValidatorTest extends AutomaticUpdatesExtensionsKernelTestBas
   }
 
   /**
-   * Data provider for testRelease().
+   * Data provider for testPreApplyException().
    *
    * @return array[]
    *   The test cases.
    */
-  public function providerTestRelease() {
+  public function providerTestPreApplyException(): array {
+    $fixtures_folder = __DIR__ . '/../../../fixtures/update_release_validator';
     return [
-      'semver, supported update' => ['semver_test', '8.1.0', '8.1.1', FALSE],
-      'semver, update to unsupported branch' => ['semver_test', '8.1.0', '8.2.0', TRUE],
-      'legacy, supported update' => ['aaa_update_test', '8.x-2.0', '8.x-2.1', FALSE],
-      'legacy, update to unsupported branch' => ['aaa_update_test', '8.x-2.0', '8.x-3.0', TRUE],
+      'semver, supported update' => ['semver_test', '8.1.0', '8.1.1', "$fixtures_folder/semver_supported_update.staged.installed.json", FALSE],
+      'semver, update to unsupported branch' => ['semver_test', '8.1.0', '8.2.0', "$fixtures_folder/semver_unsupported_update.staged.installed.json", TRUE],
+      'legacy, supported update' => ['aaa_update_test', '8.x-2.0', '8.x-2.1', "$fixtures_folder/legacy_supported_update.staged.installed.json", FALSE],
+      'legacy, update to unsupported branch' => ['aaa_update_test', '8.x-2.0', '8.x-3.0', "$fixtures_folder/legacy_unsupported_update.staged.installed.json", TRUE],
     ];
   }
 
+  /**
+   * Tests updating to a release during pre-apply.
+   *
+   * @param string $project
+   *   The project to update.
+   * @param string $installed_version
+   *   The installed version of the project.
+   * @param string $target_version
+   *   The target version.
+   * @param string $staged_installed
+   *   Path of `staged.installed.json` file. It will be used as the virtual
+   *   project's staged `vendor/composer/installed.json` file.
+   * @param bool $error_expected
+   *   Whether an error is expected in the update.
+   *
+   * @dataProvider providerTestPreApplyException
+   */
+  public function testPreApplyException(string $project, string $installed_version, string $target_version, string $staged_installed, bool $error_expected): void {
+    $this->enableModules(['aaa_automatic_updates_test', $project]);
+
+    $module_info = ['version' => $installed_version, 'project' => $project];
+    $aaa_automatic_updates_test_info = ['version' => '7.0.0', 'project' => 'aaa_automatic_updates_test'];
+    $this->config('update_test.settings')
+      ->set("system_info.$project", $module_info)
+      ->set("system_info.aaa_automatic_updates_test", $aaa_automatic_updates_test_info)
+      ->save();
+
+    // Path of `active.installed.json` file. It will be used as the virtual
+    // project's active `vendor/composer/installed.json` file.
+    $active_installed = __DIR__ . '/../../../fixtures/update_release_validator/active.installed.json';
+    $this->assertFileIsReadable($active_installed);
+    $this->assertFileIsReadable($staged_installed);
+    $this->setReleaseMetadataForProjects([
+      'aaa_automatic_updates_test' => __DIR__ . "/../../../../../tests/fixtures/release-history/aaa_automatic_updates_test.9.8.2.xml",
+      $project => __DIR__ . "/../../../fixtures/release-history/$project.1.1.xml",
+      'drupal' => __DIR__ . '/../../../../../tests/fixtures/release-history/drupal.9.8.2.xml',
+    ]);
+
+    // Copying `active.installed.json` and 'staged.installed.json' to the
+    // virtual project's  active and staged directories respectively.
+    $active_dir = $this->container->get('package_manager.path_locator')->getProjectRoot();
+    copy($active_installed, "$active_dir/vendor/composer/installed.json");
+    $listener = function (PreApplyEvent $event) use ($staged_installed): void {
+      $stage_dir = $event->getStage()->getStageDirectory();
+      copy($staged_installed, $stage_dir . "/vendor/composer/installed.json");
+    };
+    $this->container->get('event_dispatcher')->addListener(PreApplyEvent::class, $listener, 1000);
+
+    if ($error_expected) {
+      $expected_results = [
+        ValidationResult::createError(
+          ["Project $project to version " . LegacyVersionUtility::convertToSemanticVersion($target_version)],
+          t('Cannot update because the following project version is not in the list of installable releases.')
+        ),
+      ];
+    }
+    else {
+      $expected_results = [];
+    }
+
+    // Always updating aaa_automatic_updates_test to 7.0.1(valid release) along
+    // with the project provided for test.
+    $this->assertUpdateResults(
+      [
+        'aaa_automatic_updates_test' => '7.0.1',
+      ],
+      $expected_results,
+      PreApplyEvent::class
+    );
+  }
+
 }
diff --git a/src/ProjectInfo.php b/src/ProjectInfo.php
index c725d7ca39aafe5c33f6707b2e23794dd2ffb466..09d0ed8eafdf7908164596600097325b1e572eaf 100644
--- a/src/ProjectInfo.php
+++ b/src/ProjectInfo.php
@@ -86,7 +86,8 @@ final class ProjectInfo {
    *   If the project information is available, an array of releases that can be
    *   installed, keyed by version number; otherwise NULL. The releases are in
    *   descending order by version number (i.e., higher versions are listed
-   *   first).
+   *   first). The currently installed version of the project, and any older
+   *   versions, are not considered installable releases.
    *
    * @throws \RuntimeException
    *   Thrown if there are no available releases.