When installing Magento 2 software from command line (eg. via bin/magento setup:install --<option>=<value> ) with some Magento 2 extensions or custom module included (eg. MyVendor_MyModule) included, the install may fail at the 'Magento_InventorySales' level with such an error:

Unable to apply patch Magento\InventorySales\Setup\Patch\Schema\InitializeWebsiteDefaultSock
for module Magento_InventorySales. Original exception message: The default website isn't defined. Set the website and try again.

You may have the same scenario when submitting an extension on Marketplace, the extension may fail the "Installation & Varnish Test" with the same or similar error. If you download the report.json file provided for the Installation & Varnish Test Results and check the last output log for the failed message, for example:

{
  "tool": "varnish",
  "status": "FAIL",
  "reports": [
    {
      "php_version": "7.4",
      "magento_platform": "M2",
      "magento_edition": "ce",
      "magento_version": "2.4.3",
      "tool": "varnish",
      "vendor": "myvendorname",
      "extension": "module-mypackagename",
      "version": "2.3.8",
      "platform": "m2",
      "magento_cloud_docker": "1.2.4",
      "status": "FAIL",
      "date": "2021-10-11T15:43:35Z",
      "details": {
        "exit_code": 1,
        "commands": [
          {
            "command": "composerConfigRepository0",
            "output": "Finished with the \"0\" exit code."
          },
          .....
          {
          "command": "docker-compose -f docker-compose.yml run 
            --rm deploy cloud-deploy",
  	 		  ..
             \n  The command \"/bin/bash -c \"set -o pipefail; 
                php ./bin/magento setup:install 
  			  \n   -n --ansi --no-interaction --cleanup-database 
              --session-save='db' --use-se  
  			  \n  cure-admin='1' --use-rewrites='1' 
              --currency='USD' --base-url='http://magen  
  			  \n  to2.docker/' --base-url-secure='https://magento2.docker/'
               --backend-frontna  
  			  \n  me='admin' --language='en_US' -- 
               timezone='America/Los_Angeles'
               --db-host='d  
  			  \n  b' --db-name='magento2' --db-user='magento2' 
              --db-password='******' --admin  
  			  \n  -user='admin' --admin-firstname='Admin' 
               --admin-lastname='Username' --admin  
  			  \n  -email='[email protected]' 
               --admin-password='******' --search-engine='elast  
  			  \n  icsearch7' --elasticsearch-host='elasticsearch' 
               --elasticsearch-port='9200'  
  			  \n   | tee -a /app/var/log/install_upgrade.log\"\" 
               failed. 
               \u001b[33mIn PatchApplier.p 
  			  \n  hp line 247:\u001b[39m                                                            
  			  \n  \u001b[37;41m                                                                    
  			  \n              \u001b[39;49m 
               ....
               ....			 
  			  \n  \u001b[37;41m  Unable to apply 
               patch Magento\\InventorySales\\Setup\\Patch\\Schema\\I 
  			  \n  nitializeW  \u001b[39;49m                                                         
  			  \n  \u001b[37;41m  ebsiteDefaultSock for 
               module Magento_InventorySales. Original exc  
  			  \n  eption mes  \u001b[39;49m                                                         
  			  \n  \u001b[37;41m  sage: The default website
                isn't defined. Set the website and try   
  			  \n  again.   }                                                          
           ....
          }
        ]
      }
    },
}


You can see the same error :

Unable to apply patch Magento\InventorySales\Setup\Patch\Schema\InitializeWebsiteDefaultSock
for module Magento_InventorySales. Original exception message: The default website isn't defined. Set the website and try again.

What Is The Cause?

Your Magento 2 extensions or custom modules have console commands classes that seem to break the installation.

During a fresh install, Magento 2 needs to build a list of available CLI commands before running any of them. It creates instances for all console command classes, and if they have some dependencies that aren’t fully initialized yet (eg. Magento\Framework\App\State) the installation can fail.

How To Fix This Issue?

You need to Lazy load your console command classes and their dependencies. You can try to substitute dependencies used in your console command classes with proxies.

Magento 2 by default support proxies, which extends other classes to become lazy-loaded versions of them.

Magento 2 proxy can be used as a dependency anywhere the Original class can since it implements the same interface as the original class.

Magento 2 Proxies do not need to be written/coded manually, you just need to reference a class in form of proxy (eg. \MyOriginal\MyClass\MyName\Proxy), and the class will be generated if it does not exist.

In your di configuration (eg. di.xml), you can add the proxy class into the constructor arguments instead of the Original class. The proxy will be used in place of the original class, the original class won't be instantiated, and therefore, the resource-intensive constructor operations won't perform until the Original object is used.

Follow the steps below to fix the issue:

Step 1: Check the Dependencies Used in your Console Comand Class

For example, if you have a console class MyVendor\MyModule\Console\Command\Export with these dependencies

namespace MyVendor\MyModule\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use MyVendor\MyModule\Api\ExporterInterface;
use MyVendor\MyModule\Model\Config;
use Magento\Framework\App\State;
        
class Export extends Command
{
	...
    
    /**
     * @param ExporterInterface $exporterInterface
     * @param Config $config
     * @param State $state
     */
    public function __construct(
        ExporterInterface $exporterInterface,
        Config $config,
        State $state
    ) {
        $this->exporterInterface = $exporterInterface;
        $this->config = $config;
        $this->state = $state;
        parent::__construct();
    }
	......

You can use proxies for MyVendor and Magento vendors and leave Symfony vendor since it's not relevant.
You can test each dependency to see exactly which dependency is causing the install to fail, and then proxy that dependency. Or, you can safely proxies all dependencies used.

In this case, we will proxies all dependencies used. In total three dependencies:

use MyVendor\MyModule\Api\ExporterInterface;
use MyVendor\MyModule\Model\Config;
use Magento\Framework\App\State;

Step 2: Proxies Your Dependency Classes

Go to your module etc/di.xml file and just after the CommandList type, add a new type name for MyVendor\MyModule\Console\Command\Export

For example, if your etc/di.xml has this CommandList type :

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\Console\CommandList">
        <arguments>
            <argument name="commands" xsi:type="array">
                <item name="generate" 
                  xsi:type="object">MyVendor\MyModule\Console\Command\Export</item>
            </argument>
        </arguments>
    </type> 
</config>

You can add the type name for MyVendor\MyModule\Console\Command\Export as follow :

<type name="MyVendor\MyModule\Console\Command\Export">

</type>

Now add the arguments for the 3 dependency classes, followed by \Proxy as follow :

<type name="MyVendor\MyModule\Console\Command\Export">
   <arguments>
     <argument name="exporter" 
         xsi:type="object">MyVendor\MyModule\Api\ExporterInterface\Proxy</argument>	
     <argument name="config" 
          xsi:type="object">MyVendor\MyModule\Model\Config\Proxy</argument>
     <argument name="state" 
          xsi:type="object">Magento\Framework\App\State\Proxy</argument>			
     </arguments>
</type>	

Your etc/di.xml file should now look as follow :

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <type name="Magento\Framework\Console\CommandList">
      <arguments>
        <argument name="commands" xsi:type="array">
          <item name="generate" 
             xsi:type="object">MyVendor\MyModule\Console\Command\Export</item>
        </argument>
      </arguments>
    </type>
    <type name="MyVendor\MyModule\Console\Command\Export">
      <arguments>
	<argument name="exporter" 
          xsi:type="object">MyVendor\MyModule\Api\ExporterInterface\Proxy</argument>	
	<argument name="config" 
            xsi:type="object">MyVendor\MyModule\Model\Config\Proxy</argument>
	<argument name="state" 
            xsi:type="object">Magento\Framework\App\State\Proxy</argument>			
	</arguments>
     </type>	   
</config>

Step 3: Re-install Magento 2 Software 

Now, you can re-test the fresh Magento 2 install (eg.  bin/magento setup:install --<option>=<value>) with your Magento 2 extension or custom modules included.

The install will now proceed successfully.

Step 4: Testing

1. Run one of your CLI commands

2. Check if the proxies classes for vendor MyVendor and Magento are generated under generated/code folder

ls -l generated/code/MyVendor/MyModule/Api/ExporterInterface
ls -l generated/code/MyVendor/MyModule/Model/Config
ls -l generated/code/Magento/Framework/App/State

on each check, you will see that Proxy.php file is generated

3.  Also, you can re-run setup:upgrade, re-deploy static content and re-compile

php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy
php bin/magento setup:di:compile

You will see that the proxies class for vendor MyVendor and Magento are generated under generated/code folder

Conclusion

We hope you find this guide about Magento 2 proxies helpful. Feel free to share or leave a comment below. Your opinion is much appreciated!

If you're looking for experienced Magento 2 developers  to develop custom solutions per your needs, support, maintain your site, or anything else related to Magento 2, feel free to contact us

Tags: magento-2-backend-development