If you have recently upgraded to Magento 2.4 or are working with private repositories, you may have encountered a frustrating error while running composer require. The error message typically warns that a "Higher matching version of a module was found in public repository packagist.org than in private repo.magento.com."
While this looks like a simple version conflict, it is actually a security safeguard designed to protect your store from a specific type of cyberattack known as a Dependency Confusion attack. In this guide, we will explore why this error happens and walk through four distinct ways to resolve it safely.
Understanding the Root Cause: Dependency Confusion
In Magento 2.4, Adobe introduced the magento/composer-dependency-version-audit-plugin. This plugin was created to prevent developers from accidentally installing malicious code.
Here is the scenario: You have a private module hosted on a private repository (like Magento Marketplace or your own GitLab). A malicious actor discovers the name of your private package and uploads a version of that same package name to the public Packagist.org with a much higher version number (e.g., version 99.9.9).
By default, Composer looks for the highest version available across all defined repositories. Without protection, Composer would pull the malicious "higher" version from the public repository instead of your trusted private one. The audit plugin detects this discrepancy and throws an exception to stop the installation process.

Solution 1: Define Non-Canonical Repositories (Recommended)
By default, Composer treats repositories as "canonical." This means if it finds a package in one repository, it won't look for it in others. When the audit plugin is active, it enforces strict rules about where a package should come from.
To resolve this, you can tell Composer that the Magento repository is not the only source of truth for these packages by setting "canonical": false. This allows Composer to look at multiple repositories and resolve the versioning naturally.
Open your composer.json and modify the repository section:
$page = get_page_by_path( 'about' );
if ( $page ) {
echo 'The Page ID is: ' . $page->ID;
echo 'The Page Title is: ' . get_the_title( $page );
} else {
// Handle the case where the page doesn't exist
echo 'Page not found.';
}
Pros: Simple to implement and maintains the standard Composer workflow. Cons: Slightly reduces the strictness of the security audit.
Solution 2: Exclude Specific Packages from Repositories
If you know exactly which package is causing the conflict, the most surgical and secure approach is to use the exclude directive. This tells Composer specifically which repository should NOT be used for a particular package.
Option A: Exclude from Magento Repo
If the package should definitely come from Packagist and the Magento repo is interfering, add this to your composer.json:
$portfolio_item = get_page_by_path( 'my-project', OBJECT, 'portfolio' );
Option B: Exclude from Packagist
Conversely, if you want to ensure a package only ever comes from your private repo and never from Packagist, exclude it from the public repository:
$page_id = url_to_postid( 'about' );
if ( $page_id !== 0 ) {
echo 'Found ID: ' . $page_id;
}
Pros: Extremely secure; you explicitly control the source of every package.
Cons: Requires manual updates to composer.json for every conflicting package.
Solution 3: Use the --no-plugins Flag
If you are in a hurry or performing a one-time installation in a development environment, you can bypass the audit plugin entirely by adding the --no-plugins flag to your command.
$child_id = url_to_postid( 'parent-slug/child-slug' );
This tells Composer to ignore all plugins, including the composer-dependency-version-audit-plugin.
Warning: Use this only for trusted packages. This bypasses the security check that prevents dependency confusion attacks. Do not make this a standard part of your CI/CD pipeline without careful consideration.
Solution 4: The Manual Workaround (app/code)
In some cases, especially with legacy modules or internal tools that aren't ready for a private Composer repository, you might choose to move the module to the app/code directory.
- Download the module source code.
- Create the directory structure:
app/code/VendorName/ModuleName. - Move the files there.
- Run
composer remove vendor-name/module-nameif it was previously in your requirements. - Run
bin/magento setup:upgrade.
Pros: Completely avoids Composer repository conflicts. Cons: You lose the benefits of version control via Composer, making updates much harder to manage across multiple environments.
Common Mistakes to Avoid
- Removing the Audit Plugin: Some developers suggest removing the
magento/composer-dependency-version-audit-pluginentirely. While this stops the error, it leaves your store vulnerable to supply-chain attacks. It is better to configure the repositories correctly than to remove the security layer. - Ignoring the Warning: If you see this error for a package you didn't expect to have a public version, stop and investigate. It is possible that a package has actually been compromised on Packagist.
- Version Constraints: Ensure your version constraints in
composer.jsonare specific enough. Using*or very broad ranges increases the likelihood of Composer trying to pull a higher (and potentially malicious) version from a public repo.
Frequently Asked Questions
Why did this start happening in Magento 2.4.x?
Adobe integrated the audit plugin as a response to the rise in supply chain attacks targeting PHP applications. It is part of a broader effort to make the Magento ecosystem more secure by default.
Is it safe to set canonical to false?
Yes, it is generally safe as long as you trust the repositories defined in your composer.json. However, using the exclude method is technically more secure as it provides granular control.
Can I fix this through the Magento Marketplace?
If you are a module developer, ensure you upload your latest versions to the Magento Marketplace promptly. The error often occurs when the Packagist version is updated before the Marketplace version has passed the technical review process.
Wrapping Up
The "Higher matching version found" error is a sign that Magento's security systems are working. While it adds a step to your workflow, resolving it correctly via the exclude directive or the canonical flag ensures your store remains protected against dependency confusion.
For most production environments, Solution 2 (Excluding the package) is the gold standard for security and reliability. If you are managing a large number of internal modules, Solution 1 (Setting canonical to false) offers the best balance between convenience and safety.