6

I get the following error when running bin/magento setup:di:compile:

Errors during configuration scanning:
        IntegerNet\SolrSuggest\Implementor\Factory\AppFactory
                Invalid Factory for nonexistent class IntegerNet\SolrSuggest\Implementor\Factory\App in file [...]/vendor/integer-net/solr-magento2/src/Model/Cache.php

The AppFactory is actually a real interface from a library, it should not be generated by Magento. As far as I understood the generation, factories are only generated if the class does not exist. I double checked that the file exists and the directory is registered in vendor/composer/autoload_psr4.php.

This is how the class that depends on the factory looks like:

Cache.php

<?php
namespace IntegerNet\Solr\Model;
use IntegerNet\SolrSuggest\Implementor\Factory\AppFactory;
class Cache
{
    /**
     * @var AppFactory
     */
    private $appFactory;
    public function __construct(AppFactory $appFactory)
    {
        $this->appFactory = $appFactory;
    }
}

And this is the factory:

AppFactory.php

<?php
namespace IntegerNet\SolrSuggest\Implementor\Factory;
use IntegerNet\SolrSuggest\Implementor\Factory\CacheWriterFactory;
use IntegerNet\SolrSuggest\Implementor\Factory\ConfigFactory;
interface AppFactory extends ConfigFactory, CacheWriterFactory
{
}

I defined a preference for the interface in di.xml:

<preference for="IntegerNet\SolrSuggest\Implementor\Factory\AppFactory" type="IntegerNet\Solr\Model\Bridge\AppFactory" />

Any idea what I can do about these messages?

Observation

In developer mode where I don't explicitly run the compile command, I don't get any errors. And although I get these error messages, compilation runs through and everything works - which proves that the factory classes can be used.

Fabian Schmengler
  • 65,791
  • 25
  • 187
  • 421
  • http://magento.stackexchange.com/questions/69587/what-triggers-the-generation-of-a-factory-in-magento-2 may this help – Jackson Oct 25 '16 at 08:51
  • @AnkitShah unfortunately not, all agree that generation only takes place if the class does not exist, which I also thought, but does not seem to be the case for me. – Fabian Schmengler Oct 25 '16 at 08:53

3 Answers3

2

That's an interesting issue and I'm not entirely sure why is this happening.

What I can suggest is debugging directly in the _findMissingClasses method from Magento/Setup/Module/Di/Code/Scanner/PhpScanner that's where the error is coming from:

protected function _findMissingClasses($file, $classReflection, $methodName, $entityType)
{
    $missingClasses = [];
    if ($classReflection->hasMethod($methodName)) {
        $constructor = $classReflection->getMethod($methodName);
        $parameters = $constructor->getParameters();
        /** @var $parameter \ReflectionParameter */
        foreach ($parameters as $parameter) {
            preg_match('/\[\s\<\w+?>\s([\w\\\\]+)/s', $parameter->__toString(), $matches);
            if (isset($matches[1]) && substr($matches[1], -strlen($entityType)) == $entityType) {
                $missingClassName = $matches[1];
                try {
                    if (class_exists($missingClassName)) {
                        continue;
                    }
                } catch (\RuntimeException $e) {
                }
                $sourceClassName = $this->getSourceClassName($missingClassName, $entityType);
                if (!class_exists($sourceClassName) && !interface_exists($sourceClassName)) {
                    $this->_log->add(
                        Log::CONFIGURATION_ERROR,
                        $missingClassName,
                        "Invalid {$entityType} for nonexistent class {$sourceClassName} in file {$file}"
                    );
                    continue;
                }
                $missingClasses[] = $missingClassName;
            }
        }
    }
    return $missingClasses;
}

That method is called from the _fetchFactories method which also logs the same error so you need to find out, where the error is coming from exactly and from there you should be able to start debugging:

protected function _fetchFactories($reflectionClass, $file)
{
    $factorySuffix = '\\'.ucfirst(FactoryGenerator::ENTITY_TYPE);
    $absentFactories = $this->_findMissingClasses(
        $file,
        $reflectionClass,
        '__construct',
        ucfirst(FactoryGenerator::ENTITY_TYPE)
    );
    foreach ($absentFactories as $key => $absentFactory) {
        if (substr($absentFactory, -strlen($factorySuffix)) == $factorySuffix) {
            $entityName = rtrim(substr($absentFactory, 0, -strlen($factorySuffix)), '\\');
            $this->_log->add(
                Log::CONFIGURATION_ERROR,
                $absentFactory,
                'Invalid Factory declaration for class ' . $entityName . ' in file ' . $file
            );
            unset($absentFactories[$key]);
        }
    }
    return $absentFactories;
}
Raphael at Digital Pianism
  • 70,385
  • 34
  • 188
  • 352
2

Taking @Raphael's suggestion, I looked through Magento/Setup/Module/Di/Code/Scanner/PhpScanner::_findMissingClasses with the debugger on, the issue arises from this block of code

if (class_exists($missingClassName)) {
    continue;
}

In your case @fschmengler $missingClassName is IntegerNet\SolrSuggest\Implementor\Factory\AppFactory which as you said is an interface not a class.

Revising the core code to

if (interface_exists($missingClassName) || class_exists($missingClassName)) {
    continue;
}

seems to eliminate the problem. Maybe this is a bug worth mentioning to the Magento developers?

quickshiftin
  • 1,416
  • 1
  • 14
  • 37
0

I had similar errors

Interception cache generation... 6/9 [==================>---------]  66% 58 secs 442.0 MiBErrors during configuration scanning:
        Magento\Company\Api\Data\CompanyInterfaceFactory
                Invalid Factory for nonexistent class Magento\Company\Api\Data\CompanyInterface in file /home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/CompaniesFixture.php
        Magento\NegotiableQuote\Model\NegotiableQuoteFactory
                Invalid Factory for nonexistent class Magento\NegotiableQuote\Model\NegotiableQuote in file /home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/NegotiableQuotesFixture.php
        Magento\Company\Model\ResourceModel\Company\CollectionFactory
                Invalid Factory for nonexistent class Magento\Company\Model\ResourceModel\Company\Collection in file /home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/NegotiableQuotesFixture.php
        Magento\NegotiableQuote\Api\Data\HistoryInterfaceFactory
                Invalid Factory for nonexistent class Magento\NegotiableQuote\Api\Data\HistoryInterface in file /home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/NegotiableQuotesFixture.php
        Magento\SharedCatalog\Model\ResourceModel\SharedCatalog\CollectionFactory
                Invalid Factory for nonexistent class Magento\SharedCatalog\Model\ResourceModel\SharedCatalog\Collection in file /home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/SharedCatalogsFixture.php
Total Errors Count: 5

I solved these errors by deleting the following files:

/home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/NegotiableQuotesFixture.php
/home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/SharedCatalogsFixture.php
/home/companyde/staging-m2.company.de/setup/src/Magento/Setup/Fixtures/CompaniesFixture.php

I think these files are from magento enterprise B2B module. I removed the module with composer remove but the files where not deleted as well and caused the error.

Black
  • 3,310
  • 4
  • 31
  • 110
  • ➕ similar experience. Running composer install, bin/magento c:c, and bin/magento set:up resolved this issue for me. – Mike Dubs Nov 15 '22 at 19:01