diff --git a/drupalci.yml b/drupalci.yml
index 2bcc8d189c8dcd865af6e44552386a17b5d9f001..3cd1b3cc07ae5dc0f4bb4bc8816680aba848a582 100644
--- a/drupalci.yml
+++ b/drupalci.yml
@@ -11,8 +11,8 @@ build:
         commands:
           # Install rsync.
           - DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y rsync
-          # Update to Composer 2.5.5.
-          - composer self-update 2.5.5
+          # Update to latest Composer.
+          - composer self-update
           # @todo Replace in favor of commit-code-check.sh once https://www.drupal.org/project/drupal/issues/3314100 lands.
           - modules/contrib/automatic_updates/scripts/commit-code-check.sh --drupalci
         halt-on-fail: true
diff --git a/package_manager/src/ComposerInspector.php b/package_manager/src/ComposerInspector.php
index 7559e4b38450ab83447c3513642e203448c3093c..1a4fc0725aaa6807fdf9aee92bdca5f93bbd3eb8 100644
--- a/package_manager/src/ComposerInspector.php
+++ b/package_manager/src/ComposerInspector.php
@@ -317,23 +317,35 @@ class ComposerInspector implements LoggerAwareInterface {
     $packages_data = $this->getPackageTypes($packages_data, $working_dir);
 
     foreach ($packages_data as $name => $package) {
-      $path = realpath($package['path']);
+      $path = $package['path'];
 
       // We expect Composer to report that metapackages' install paths are the
       // same as the working directory, in which case InstalledPackage::$path
       // should be NULL. For all other package types, we consider it invalid
       // if the install path is the same as the working directory.
-      if ($package['type'] === 'metapackage') {
-        if ($path === $working_dir) {
-          $packages_data[$name]['path'] = NULL;
+      // @todo Remove this handling of metapackage paths when Composer 2.5.7 or
+      //   later is required, in https://drupal.org/i/3365133.
+      if (isset($package['type']) && $package['type'] === 'metapackage') {
+        // TRICKY: until Composer 2.5.6, metapackages returned the current
+        // working directory instead of NULL.
+        // @see https://github.com/composer/composer/commit/3a48e393756e8b0387925aa327f45a30128b4556
+        $packages_data[$name]['path'] = NULL;
+        // @todo Remove the if-branch when the minimum Composer version is raised to >=2.5.6.
+        if (Semver::satisfies($this->getVersion(), '<2.5.6')) {
+          if ($path !== $working_dir) {
+            throw new \UnexpectedValueException("Metapackage '$name' is installed at unexpected path: '$path', expected '$working_dir'");
+          }
         }
-        else {
-          throw new \UnexpectedValueException("Metapackage '$name' is installed at unexpected path: '$path', expected '$working_dir'");
+        elseif ($path !== NULL) {
+          throw new \UnexpectedValueException("Metapackage '$name' is installed at unexpected path: '$path', expected NULL");
         }
       }
       elseif ($path === $working_dir) {
         throw new \UnexpectedValueException("Package '$name' cannot be installed at path: '$path'");
       }
+      else {
+        $packages_data[$name]['path'] = realpath($path);
+      }
     }
     $packages_data = array_map(InstalledPackage::createFromArray(...), $packages_data);
 
diff --git a/package_manager/src/InstalledPackage.php b/package_manager/src/InstalledPackage.php
index f3cff37081d70c956d4d0a20e4019123ab4921c2..ec5b1de935ea585b7f16f74d7f6aeaf7ec5ea249 100644
--- a/package_manager/src/InstalledPackage.php
+++ b/package_manager/src/InstalledPackage.php
@@ -40,9 +40,12 @@ final class InstalledPackage {
    */
   public static function createFromArray(array $data): static {
     $path = isset($data['path']) ? realpath($data['path']) : NULL;
-    assert(($data['type'] === 'metapackage') === is_null($path), 'Metapackage install path must be NULL.');
+    // Fall back to `library`.
+    // @see https://getcomposer.org/doc/04-schema.md#type
+    $type = $data['type'] ?? 'library';
+    assert(($type === 'metapackage') === is_null($path), 'Metapackage install path must be NULL.');
 
-    return new static($data['name'], $data['version'], $path, $data['type']);
+    return new static($data['name'], $data['version'], $path, $type);
   }
 
   /**
diff --git a/package_manager/tests/src/Kernel/ComposerInspectorTest.php b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
index e83db4f631bba8656d20de80426237e546fc4370..b956182b9666e756dc9b0747e76baa43b02dff53 100644
--- a/package_manager/tests/src/Kernel/ComposerInspectorTest.php
+++ b/package_manager/tests/src/Kernel/ComposerInspectorTest.php
@@ -348,8 +348,8 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase {
    *
    * @covers ::getInstalledPackagesList
    *
-   * @testWith [true, "<PROJECT_ROOT>", null]
-   *   [true, "<PROJECT_ROOT>/another/directory", "Metapackage 'test/package' is installed at unexpected path: '<PROJECT_ROOT>/another/directory', expected '<PROJECT_ROOT>'"]
+   * @testWith [true, null, null]
+   *   [true, "<PROJECT_ROOT>/another/directory", "Metapackage 'test/package' is installed at unexpected path: '<PROJECT_ROOT>/another/directory', expected NULL"]
    *   [false, null, null]
    *   [false, "<PROJECT_ROOT>", "Package 'test/package' cannot be installed at path: '<PROJECT_ROOT>'"]
    */