6

First off, very importantly: This error ONLY happens in production mode. In developer mode it seems to be fine. So those of you who will tell me to clear var/generation: That would break production mode!

Also, this is a 3rd party module that we didn't develop ourselves. I guess I will be contacting the developers of that.

That being said, I want to know how I could debug and solve this myself if I had no other choice. Here is what it looks like in the browser (yes, unlike most Magento exception printing it's all on one line, the browser will linewrap it to avoid horizontal scrolling)

Fatal error: Uncaught TypeError: Argument 1 passed to MGS\Brand\Helper\Data::__construct() must be an instance of Magento\Framework\App\Helper\Context, instance of Magento\Framework\ObjectManager\ObjectManager given, called in /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php on line 93 and defined in /mypath/app/code/MGS/Brand/Helper/Data.php:38 Stack trace: #0 /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php(93): MGS\Brand\Helper\Data->__construct(Object(Magento\Framework\ObjectManager\ObjectManager)) #1 /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/Compiled.php(88): Magento\Framework\ObjectManager\Factory\AbstractFactory->createObject('Mgs\\Brand\\Helpe...', Array) #2 /mypath/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php(71): Magento\Framework\ObjectManager\Factory\Compiled->create('Mgs\\Brand\\Helpe...') #3 /mypath/lib/internal/Magento/Framework/View/TemplateEngine/Php.ph in /mypath/app/code/MGS/Brand/Helper/Data.php on line 38

So let me format that for your viewing pleasure:

Fatal error: Uncaught TypeError: Argument 1 passed to MGS\Brand\Helper\Data::__construct() must be an instance of Magento\Framework\App\Helper\Context, instance of Magento\Framework\ObjectManager\ObjectManager given, 
called in /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php on line 93 and defined in /mypath/app/code/MGS/Brand/Helper/Data.php:38 
Stack trace: 
#0 /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/AbstractFactory.php(93): MGS\Brand\Helper\Data->__construct(Object(Magento\Framework\ObjectManager\ObjectManager)) 
#1 /mypath/lib/internal/Magento/Framework/ObjectManager/Factory/Compiled.php(88): Magento\Framework\ObjectManager\Factory\AbstractFactory->createObject('Mgs\\Brand\\Helpe...', Array) 
#2 /mypath/lib/internal/Magento/Framework/ObjectManager/ObjectManager.php(71): Magento\Framework\ObjectManager\Factory\Compiled->create('Mgs\\Brand\\Helpe...') 
#3 /mypath/lib/internal/Magento/Framework/View/TemplateEngine/Php.ph 
in /mypath/app/code/MGS/Brand/Helper/Data.php on line 38

Notice that the stack trace is cut off at the end of line #3, so I don't know where this could really be called from!

How can I debug this? Is there any way to get the full backtrace?

And how can this only happen in production mode but be totally fine in developer mode?

I'm running Magento 2.1.0 on php-fpm 7.0.12 in an ubuntu-based docker container on an Ubuntu 16.04 server.

5

Just to clarify as it seems to happen to a lot of people, there's two possible cases.

Let's use the class Bar for all those cases:

class Bar {

    public function __construct(
        \First\Argument $first,
        \Second\Argument $second
    ) {
        // Constructor code
    }
}

NB: please note that in Magento 2, the $data array parameter always comes last: Magento 2: what is the $data array constructor parameter?

Case 1

You have class Foo that extends Bar

class Foo extends Bar {

     public function __construct(
         \First\Argument $first,
         \Second\Argument $second,
         \Test $test,
         \Testtwo $testtwo
     ) {
         parent::__construct($second, $first);
     }
}

The problem : in that case, the call to the parent constructor does not provide the arguments in the right order. To fix that you must match the parent constructor:

parent::__construct($first, $second);

Case 2

You have class Foo that extends Bar

class Foo extends Bar {

     public function __construct(
         \First\Argument $first,
         \Second\Argument $second,
         \Test $test,
         \Testtwo $testtwo
     ) {
         parent::__construct($first, $second);
     }
}

I hear you saying:

What the hell is wrong with this one ?

Well, the answer is : nothing!

Even if that class looks okay you might get the Uncaught TypeError: Argument X passed to Class must be an instance of Class2 error because of the Magento 2 class generation system.

To fix that, simply delete var/generation folder

Extra Case

You have class Foo that extends Bar

class Foo extends Bar {

     public function __construct(
         \Test $test,
         \Testtwo $testtwo,
         \First\Argument $first,
         \Second\Argument $second
     ) {
         parent::__construct($first, $second);
     }
}

In that particular case, the static tests will complain about the order of parameters in the constructor. To fix that you should change:

 public function __construct(
     \First\Argument $first,
     \Second\Argument $second,
     \Test $test,
     \Testtwo $testtwo
 ) {
     parent::__construct($first, $second);
 }
  • 2
    The order of the arguments is irrelevant afaik, as long as the optional parameters (the ones with default values like $data = [] for example, come last. However, if more then one parameter is optional, the order of those doesn't matter (e.g. $data = [], $adapter = null works just as $adapter = null, $data = []); Deleting var/generation (or at least the generated class in question) always has to be done after changing the signature of a public method, even in developer mode. – Vinai Nov 4 '16 at 8:56
  • @Vinai that's right, I removed that bit it was probably confusing. – Raphael at Digital Pianism Nov 4 '16 at 9:01
  • 2
    @Vinai. The order is irrelevant but the code sniffer with the ECGM2 standards complains about it. It requires this order: Parent class mandatory arguments, class specific mandatory arguments, optional arguments. – Marius Nov 4 '16 at 10:24
  • 2
    What a stupid rule. – Vinai Nov 4 '16 at 10:24
  • 2
    Aparently I was wrong. It's not the ECGM2 standard. It's the static test that complains about itbin/magento dev:tests:run static. This is what complains about the order of the parameters – Marius Nov 4 '16 at 11:12
1

Apparently I was stupid.

I could have sworn that I tried deleting var/generation and then re-compiling. But now I did that "again" and it solved the problem.

It turns out that running bin/magento setup:di:compile does NOT clear var/generation before recompiling. I assumed that it would do that, and that's why my previous re-compiling didn't solve the problem.

Maybe this could be a good idea for the Magento developers to consider. Manually deleting files shouldn't be necessary when so many CLI commands are offered.

  • on third thoughts, I'm still confused. a week later I'm having the same problem again, and this time I clearly cannot solve it by deleting var/generation, the problem persists. don't have a solution yet. – peedee Nov 15 '16 at 2:56
0

There is a workaround for this problem if you are sure that the order of the arguments is good and your module works in developer mode. You have to create an empty class, which extends the problematic class. In your case:

namespace Foo\Bar;
class Something extends \MGS\Brand\Helper\Data
{
}

then create a new preference in di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="MGS\Brand\Helper\Data" type="Foo\Bar\Something" />
</config>

then just recompile with php magento setup:di:compile. Then it should work.

There was a discussion about this also on the Magento Github repository.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.