How to fix “Area code is already set”

This article provides background information and a recommended approach to resolving the Magento error:

  • Area code is already set, or
    area-code-is-already-set
  • Area is already set
    Screenshot 2019-04-04 at 12.12.13

 

What does this error mean and why does it occur?

This error typically arises when a third party extension includes an incorrect usage of the method setAreaCode().

Magento uses area codes to define which parts of the application to load given a specific request context. There are four distinct ‘areas’ of the system, each with their own area code:

  • frontend
  • adminhtml
  • webapi_rest
  • CLI

The area code is set within Magento by the Magento\Framework\App\State object:

public function setAreaCode($code)
{
    $this->checkAreaCode($code);

    if (isset($this->_areaCode)) {
        throw new \Magento\Framework\Exception\LocalizedException(
            new \Magento\Framework\Phrase('Area code is already set')
        );
    }
    $this->_configScope->setCurrentScope($code);
    $this->_areaCode = $code;
}

Attempting to set an area code after one has already been set is forbidden by the Magento application, resulting in the error message ‘Area code is already set’ or similar.

The most common occurrence is when a third party extension has included a call to setAreaCode() within a CLI Command construct() method. This is because the Magento\Framework\App\State object (where the area code is set) is a single instance object and whenever Magento runs a Command, it will first instantiate every Command object in the system, and run the corresponding construct methods.

Therefore rather than the construct, the correct location for setAreaCode() to be called from is the beginning of your CLI Command execute() method, ie:

Correct

Incorrect

protected function execute(...)
{
    try {
        $state = ObjectManager::getInstance()->get('\Magento\Framework\App\State');
        $state->setAreaCode('frontend');
    }
}
public function __construct(...)
{
    $state = ObjectManager::getInstance()->get('\Magento\Framework\App\State');
    $state->setAreaCode('frontend');
}

 

What does the Klevu code do?

Klevu’s code respects the above principles by only ever setting the area code within the execute() method of a console Command:

Here is an example of correct usage from the Klevu code, within an execute method:
klevu/module-productsearch/Console/Command/SyncStoreView.php

protected function execute(InputInterface $input, OutputInterface $output)
{
    $this->appState->setAreaCode('frontend');
}

Here is an example of correct usage taken from the Magento core code, within an execute method:
magento/module-catalog/Console/Command/ProductAttributesCleanUp.php

protected function execute(InputInterface $input, OutputInterface $output)
{
    $output->setDecorated(true);
    $this->appState->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);
}

 

How to fix it?

The solution will differ depending on the extensions you have installed on your specific codebase, but some investigation and development work will be required to find and amend the offending code to conform with the Magento standard guidelines.

Step 1

Search within any extensions for usages of the setAreaCode() method, and check where they are being called from.

Step 2

If an incorrect usage is found within a third party extension, contact the vendor to have them amend the code to conform with the below guidelines. Alternatively if you have a development team or if the offending code resides within your own scope, you can amend this yourself using the following guidelines.

Guidelines to avoid the error

Use the following rules to identify incorrect usages, and to ensure this error does not occur in your application:

  • Never set area code within the constructor, as the constructor is always triggered when classes are loaded and can cause this error even from a seemingly unrelated extension.
  • If you want to set an area code on the command line, you should do so at the top of the CLI Command’s ‘execute’ method as this way it will be triggered as intended only when that particular Command is run.
  • You should not change area code in the frontend or in admin. Area code is set based on route, so every time a site is launched it decides a specific area code. In this scenario you should consider using emulateAreaCode().
  • If you want to set or check if an area code has been set, you should do it within a try { } catch { } and correctly handle any thrown Exceptions, depending on your intended logic.
  • Do not set an area code unless absolutely necessary. The majority of operations can be done without this.
  • Use the core \Magento\Framework\App\State::emulateAreaCode method to temporarily set the area code:
public function exampleCodeRequiringCustomAreaCode()
{
    // currently in another scope, eg. adminhtml or webapi_rest
    $this->appState->emulateAreaCode(
        'frontend',
        function ()  {
            // add your frontend scope related functionality
        }
    );
}

 

Further Reading

If you would like to find out more about this particular Magento error message, you can search for “area code already set” or read the following community articles: