Sometimes, when you’re working with a Magento 2 command line script, you’ll see an uncaught exception that looks like the following.
Area code not set: Area code must be set before starting a session
Areas in Magento refer to different sections of an application (like frontend
cart, or the adminhtml
admin console) available at different URLs (/
vs /admin
vs /rest
vs /etc
). Magento 2’s done some work formalizing the somewhat haphazard area system implemented in Magento 1, but there are still some rough edges. Some code expects to be run from a certain area. However, as areas are tied to URLs, a command line scripts has no area.
Rather than run code and hope for the best, much of Magento 2 will halt with the above exception when there’s a part of the code that checks for area, but no area exists. If you want to access these parts of the system, you’ll need to use Magento’s App State object to manually set an area code. You can do so with the following automatic constructor dependency injection, property assigning, and call in your command’s execute function.
/* ... */
protected $appState;
public function __construct(
Magento\Framework\App\State $appState,
$name=null
)
{
$this->appState = $appState;
parent::__construct($name);
}
public function execute()
{
$originalArea = $this->appState->getAreaCode();
$this->appState->setAreaCode('frontend');
/* ... your command code here ... */
//reset original code
$this->appState->setAreaCode($originalArea);
}
/* ... */
The Magento\Framework\App\State
object is the same object Magento uses to set an area code, (remember, automatic constructor dependency injection objects are shared instances by default). By setting this to frontend
, Magento will act as though you’re running code in the front end cart application. This should suppress the Area code not set exceptions.
Update 1:An earlier version of this post (prior to September 12th, 2018) recommended setting the actual area code in the constructor itself. This turned out to be an incorrect approach. That’s because the Magento\Framework\App\State
object is a single instance object and whenever Magento runs a command it will instantiate every command object in the system.
This means the original code was changing the state for any command that was instantiated after it — which may have introduced subtle, hard to diagnose, bugs. By changing the state in the execute method (and changing it back at the end) we removed the possibility that the area change will have an impact outside our code.
Update 2: We’ve had reports from users that, in more recent versions of Magento, the getAreaCode
method will thrown an exception if the area code hasn’t been set. To work around this you’ll want/need to wrap your calls in a try/catch block. We’ll leave the actual code for this as an exercise for the reader because honestly we’re a little exhausted at this point.