composer/composer · error · InvalidArgumentException

Only subclasses of BasePackage are supported

Error message

Only subclasses of BasePackage are supported

What it means

Thrown by ArrayRepository::addPackage when the supplied package does not extend BasePackage. ArrayRepository relies on BasePackage-specific behaviour (aliasing, unique-name caching) and rejects any other PackageInterface implementation.

Source

Thrown at src/Composer/Repository/ArrayRepository.php:218

        if ($this->packageMap === null) {
            $this->packageMap = [];
            foreach ($this->getPackages() as $repoPackage) {
                $this->packageMap[$repoPackage->getUniqueName()] = $repoPackage;
            }
        }

        return isset($this->packageMap[$package->getUniqueName()]);
    }

    /**
     * Adds a new package to the repository
     *
     * @return void
     */
    public function addPackage(PackageInterface $package)
    {
        if (!$package instanceof BasePackage) {
            throw new \InvalidArgumentException('Only subclasses of BasePackage are supported');
        }
        if (null === $this->packages) {
            $this->initialize();
        }
        $package->setRepository($this);
        $this->packages[] = $package;

        if ($package instanceof AliasPackage) {
            $aliasedPackage = $package->getAliasOf();
            if (null === $aliasedPackage->getRepository()) {
                $this->addPackage($aliasedPackage);
            }
        }

        // invalidate package map cache
        $this->packageMap = null;
    }

View on GitHub (pinned to c435d285c9)

Solutions

  1. Ensure the package instance extends Composer\Package\BasePackage (or one of its subclasses like CompletePackage, AliasPackage).
  2. If using a loader, use ArrayLoader which produces BasePackage instances.
  3. In tests, mock or stub a concrete BasePackage subclass rather than the interface.

Example fix

// before
$repo->addPackage(new MyCustomPackage($name, $version, $type));
// after
$pkg = new \Composer\Package\CompletePackage($name, $version, $prettyVersion);
$repo->addPackage($pkg);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!$package instanceof \Composer\Package\BasePackage) {
    throw new \InvalidArgumentException('Repository expects BasePackage, got '.get_debug_type($package));
}
$repo->addPackage($package);

Type guard

function isBasePackage(\Composer\Package\PackageInterface $p): bool
{
    return $p instanceof \Composer\Package\BasePackage;
}

Try / catch

try {
    $repo->addPackage($package);
} catch (\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'Only subclasses of BasePackage')) { /* wrap in a BasePackage/CompletePackage */ }
    else { throw $e; }
}

Prevention

When it happens

Trigger: Calling $repo->addPackage($pkg) where $pkg is a PackageInterface that is not a BasePackage subclass (e.g. a bare Package or a custom implementation extending only PackageInterface). Also reachable via AliasPackage handling in addPackage itself.

Common situations: Custom repository implementations or test doubles that pass a non-BasePackage mock. Third-party plugins that construct their own package classes.

Related errors


AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07). Data as JSON: /api/errors/2ed0f9b20c97043b. Report an issue: GitHub.