11

When attempting to send emails in Magento 2 from command-line, I encountered the exception below. While using the very same class to send emails from an frontend or backend controller was working perfectly. The issue was stricly happening using the command line interface.

Exception:

main.CRITICAL: exception 'BadMethodCallException' with message 'Missing required argument $debugHintsPath of Magento\Developer\Model\TemplateEngine\Plugin\DebugHints.' in /.../.../magento/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php:45

The issue was also only happening when trying to call a block via layout from inside the template. As soon as the block call was removed, the exception stopped showing.

Template File:

app/code/NameSpace/Module/view/frontend/email/email_notification.html

{{template config_path="design/email/header_template"}}

...

<!-- THIS LINE CAUSED THE EXCEPTION TO SHOW UP -->
{{layout handle="sales_email_order_items" order=$order area="frontend"}}

...

{{template config_path="design/email/footer_template"}}

The email was still sent with the subject line intact but the entire content was not rendered and only the error below was showing in the content section once the email was received.

Error printed inside emails:

Error filtering template: Missing required argument $debugHintsPath of Magento\Developer\Model\TemplateEngine\Plugin\DebugHints.

16

I finally found the solution to this problem in the Magento Community Forums, which was provided by @dunagan5887. I decided to share it here on magento.stackexchange.com as many may benefit from a well refered solution to this exception.

There is a link to the original Community Forum post: Email template with block

It seems that this solution, as quoted by @dunagan5887; dictates that the di.xml directive set in vendor/magento/module-developer/etc/adminhtml/di.xml is loaded.

The Solution Consists of this Simple Line of Code:

$this->_objectManager->configure($this->_configLoader->load('adminhtml'));


Please find a working version command line class below:

app/code/NameSpace/Module/Console/Command.php

<?php
namespace NameSpace\Module\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Magento\Framework\Exception\LocalizedException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CustomCommandClass extends Command
{
    public function __construct(
        \Magento\Framework\App\State $state,
        \Magento\Framework\ObjectManagerInterface $objectManager,
        \Magento\Framework\ObjectManager\ConfigLoaderInterface $configLoader
    ) {
        $state->setAreaCode('frontend'); //SET CURRENT AREA
        $objectManager->configure($configLoader->load('frontend')); //SOLUTION
        parent::__construct();
    }

    ...

}

Simply change the area from frontend to admin or global as required by your application.


[UPDATE]

Area adminhtml causing static content deploy errors

It seems that for some reasons setting the area to adminhtml is causing some errors while deploying static contents.

We were seeing errors like the following:

Fatal error: Uncaught Exception: Warning: Error while sending QUERY packet. PID=22912 in ../magento/vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php on line 228 in ../magento/vendor/magento/framework/App/ErrorHandler.php:61

I initially thought that this error would be caused by a low max_allowed_packet setting for MYSQL but as the limit was already high enough and raising it wasn't resolving the issue, I decided to dig further. After going through an elimination process I finally found out that this was the main difference between two modules using similar command functions, from which one of the modules was causing this issue as soon as enabled.

Although I haven't digged to find the source of this issue or conflict, I thought it would be a good idea to share my findings here as others may find it useful.


[UPDATE - 2]

The right method:

After upgrading Magento to 2.2.X we realized that this is the right method for setting the area:

app/code/NameSpace/Module/Console/Command.php

<?php
namespace NameSpace\Module\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Magento\Framework\Exception\LocalizedException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class CustomCommandClass extends Command
{
    public function __construct(
        \Magento\Framework\App\State $state,
    ) {
        $this->_appState = $appState;
        parent::__construct();
    }

    ...

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->_appState->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL); //SET CURRENT AREA

        ...

    }

    ...

}

Note that we do not make use of the Object Manager and that the area has to be set within the function requiring it and NOT in the constructor. This is the official way of setting the area and it should work flawlessly with all Magento 2 versions.


A list of the available areas is available in the following class:

Magento\Framework\App\Area

class Area implements \Magento\Framework\App\AreaInterface
{
    const AREA_GLOBAL = 'global';
    const AREA_FRONTEND = 'frontend';
    const AREA_ADMIN    = 'admin';
    const AREA_ADMINHTML = 'adminhtml';
    const AREA_DOC = 'doc';
    const AREA_CRONTAB = 'crontab';
    const AREA_WEBAPI_REST = 'webapi_rest';
    const AREA_WEBAPI_SOAP = 'webapi_soap';

    ...
  • Thanks a lot @ElGatito. U save my day. :) Thanks a log again – Ankit Shah May 16 '17 at 8:00
  • I have set scope as global and its working fine for me. – Rakesh Jesadiya Jan 31 '18 at 6:34
  • 1
    WARNING: Do NOT use that code ($objectManager->configure($configLoader->load('frontend'));) in the constructor of a class! If you do and load configuration from a different area than your current area, this can seriously break Magento 2! – Wesley Vestjens Feb 13 '18 at 14:41
  • @Wesley Vestjens +1 Thank you for your comment. The right method is actually very different and I have updated my answer to reflect it. Please refer to [UPDATE - 2]. – ElGatito Feb 14 '18 at 15:59
  • Actually, merely setting the area does not work if you use any part of the view layer of Magento 2 (which is required for generating PDF files in Magento 2). You will get an error regarding the following object: Magento\Developer\Model\TemplateEngine\Plugin\DebugHints because the debugHintsPath variable is not set. Using your original code to load the ADMINHTML area DI configuration works, or manually setting the debugHintsPath variable works, but there might be other broken parts. This is actually a "bug" in Magento, because it's not possible to use view layer elements in CLI. – Wesley Vestjens Feb 15 '18 at 18:20
6

As CLI in Magento doesn't have an appropriate area, I figured out the following workaround:

app/code/NameSpace/Module/etc/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">
    <!-- Add this for sending email via cli -->
    <type name="Magento\Developer\Model\TemplateEngine\Plugin\DebugHints">
        <arguments>
            <argument name="debugHintsPath" xsi:type="string">dev/debug/template_hints_storefront</argument>
        </arguments>
    </type>
</config>

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.