Avoiding entity-type errors on module installation I created a logger service that uses a config entity for configuration: https://drupal.org/project/dblog_persistent

Unfortunately, it appears that this module is not installable on a new site, because Drupal attempts to instantiate the logger service before actually installing the config entity type it depends on - the result is a PluginNotFoundException.

There has to be some way to prevent services from being instantiated until the module is installed, or not?

This is the class and constructor definition:

&lt;?php

namespace Drupal\dblog_persistent\Logger;

use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LogMessageParserInterface;
use Drupal\dblog\Logger\DbLog;
use Drupal\dblog_persistent\DbLogPersistentStorageInterface;

/**
 * Class DbLogPersistent
 *
 * @package Drupal\dblog_persistent\Logger
 */
class DbLogPersistent extends DbLog {

  /**
   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
   */
  protected $channelStorage;

  /**
   * @var \Drupal\dblog_persistent\DbLogPersistentStorageInterface
   */
  private $storage;

  /**
   * @var \Drupal\dblog_persistent\Entity\ChannelInterface[]
   */
  private $channels;

  public function __construct(Connection $connection,
                              LogMessageParserInterface $parser,
                              EntityTypeManagerInterface $manager,
                              DbLogPersistentStorageInterface $storage) {
    parent::__construct($connection, $parser);
    // The following causes an error on installation:
    $this-&gt;channelStorage = $manager-&gt;getStorage('dblog_persistent_channel');
    $this-&gt;storage = $storage;
  }


And the service definition:

services:
  dblog_persistent.storage:
    class: Drupal\dblog_persistent\DbLogPersistentStorage
    arguments:
      - '@database'
  logger.dblog_persistent:
    class: Drupal\dblog_persistent\Logger\DbLogPersistent
    arguments:
      - '@database'
      - '@logger.log_message_parser'
      - '@entity_type.manager'
      - '@dblog_persistent.storage'
    tags:
      - { name: logger }


As a hack, I could surround every function in the logger with ifs that ensure it doesn't run unless installation is complete, but that's pretty dirty. Is there at least some kind of null entity storage that the constructor could fall back on, to minimize the amount of defensive programming?
I've revised my approach here several times, but so far the cleanest solution in my opinion is:

Store the entity_type.manager service, not the storage. When the storage is used, place the whole chain $this-&gt;manager-&gt;getStorage()-&gt;loadMultiple() into a try/catch.

This avoids having to handle the special case in two places: Once in the constructor (when acquiring the storage might fail), and again in the loading function (when the storage might not exist, because it failed in the constructor).

&lt;?php

namespace Drupal\dblog_persistent\Logger;

use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LogMessageParserInterface;
use Drupal\dblog\Logger\DbLog;
use Drupal\dblog_persistent\DbLogPersistentStorageInterface;

/**
 * Class DbLogPersistent
 *
 * @package Drupal\dblog_persistent\Logger
 */
class DbLogPersistent extends DbLog {

  /**
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $manager;

  /**
   * @var \Drupal\dblog_persistent\DbLogPersistentStorageInterface
   */
  protected $storage;

  /**
   * @var \Drupal\dblog_persistent\Entity\ChannelInterface[]
   */
  private $channels;

  public function __construct(Connection $connection,
                              LogMessageParserInterface $parser,
                              EntityTypeManagerInterface $manager,
                              DbLogPersistentStorageInterface $storage) {
    parent::__construct($connection, $parser);
    $this-&gt;manager = $manager;
    $this-&gt;storage = $storage;
  }

  protected function getChannels() {
    if ($this-&gt;channels === NULL) {
      try {
        $this-&gt;channels = $this-&gt;manager
          -&gt;getStorage('dblog_persistent_channel')
          -&gt;loadMultiple();
      }
      catch (PluginNotFoundException $e) {
        $this-&gt;channels = [];
      }
    }
    return $this-&gt;channels;
  }
}