If you create a new feature with multiple components that depend on each other (e.g. a view that displays a field and the field itself), and you try to import this feature on a site lacking either of these components, the import will frequently fail.

The reason is that Features / D8 core does not seem to check configuration dependencies to ensure that they get imported in the correct order. In this case, the problem we frequently see is that Features will try to import the view before it imports the field, and this will cause features-import to die with cryptic exceptions such as:

No entity type for field title on view my_view

The manual workaround for now is to write an update hook to manually create the field before trying to features-import the rest of the feature, including the view.

Comments

Dane Powell created an issue. See original summary.

Dane Powell’s picture

Based on the issue description, I expected #2715971: Components' dependencies aren't respected during revert to solve this issue, but the scenario I describe above still fails with that patch in place.

dawehner’s picture

Just as general statement, core is using config dependencies to build a tree, see \Drupal\Core\Config\Entity\ConfigDependencyManager::createGraphConfigEntityDependencies

In this case, the problem we frequently see is that Features will try to import the view before it imports the field, and this will cause features-import to die with cryptic exceptions such as:
Did you checked whether the view has the field config and field storage config as part of its dependencies? I could imagine that \Drupal\views\Plugin\views\field\Field::calculateDependencies simply ignores field config entities.

Dane Powell’s picture

In some cases the view config is lacking an explicit dependency on the fields it displays. But even if I manually add those dependencies, the import can still fail. So maybe there are two bugs here, one with Features and one with Views.

mpotter’s picture

But Features doesn't mess with the actual *.yml file for the config export. So Features isn't going to change any of the config dependencies. Sounds like something is still missing a dependency in the actual config entity.

If D8 isn't respecting the config dependencies then that would be a core issue. So I'm curious about getting a reproducible example where the view config has the dependencies on fields that still doesn't import so we can try to debug this.

(Note: the assignment plugins that handle the dependencies are only adding module dependencies to the *.info.yml file for the feature module. Features doesn't mess with the config dependencies in the configitem.yml file itself)

mpotter’s picture

Priority: Major » Normal
Status: Active » Postponed (maintainer needs more info)

Need a procedure to reproduce this for testing.

Danny Englander’s picture

I am pretty sure I have run into this issue but I suspect it's because I am not creating my features the in the correct manner. I tried to be very granular in my approach as I would have done in Drupal 7 but no matter what I do, I still get various errors when trying to activate my features on a new site. The bottom line is that the features will not activate, mainly because of "unmet dependancies." Shall I open a separate issue?

keesje’s picture

Ran into issues "like this" too.

Dependencies:
When a config depends on a plugin in another module, that module is added as dependency to the feature.
When that module is not enabled (yet), it can be that upon feature import, features is trying to apply the config before enabling the depending module. Import will fail.

Example: add a field to a node, field uses a field formatter of a custom module. Exporting all to an already installed feature, importing that feature tries to import config without first enabling the module containing the formatter.

Problems can also occur when re-using fields in entity types that are stored in different features. Importing a feature containing only an instance configuration of a field, needs the feature containing the storage configuration of that field to be enabled.

keesje’s picture

This is likely to be related: https://www.drupal.org/node/799314

mikemadison’s picture

@mpotter the scenario i just ran into this during was something like this:

2 content types exist, both have separate features. feature 1: contains field storage for a field used in feature 2. feature 1 comes alphabetically after feature 2.

when drush fr is run, feature 2 is reverted ahead of feature 1, and since feature 2 doesn't contain the field storage for the field, it throws the error

nedjo’s picture

Status: Postponed (maintainer needs more info) » Active

We're using Configuration update manager's Configuration update base module to do imports.

That module by design only handles single-item imports, and does not include dependency handling. See these issues: #2423211: Review config dependency handling in import operation and #2426189: More user-friendly exception/error handling on revert and import. So there are inherent limitations when it comes to the use cases in this issue.

You could try Configuration synchronizer, which provides handling of updates for sets of configuration.

keesje’s picture

I think we need to separate 2 kinds of "dependencies":

  1. config-component dependencies in .yaml
  2. module dependencies in .info

The original issue discribes the first. But you are are likely to encounter the first due to the second: when a config dependency lives in another module (and features are modules) that are new module dependencies.

nedjo’s picture

I think we need to separate 2 kinds of "dependencies":

  1. config-component dependencies in .yaml
  2. module dependencies in .info

Yes. Addressing the second would prevent many, but not all, errors in the first.

when a config dependency lives in another module (and features are modules) that are new module dependencies.

Yes, that's one case dependencies, which is being discussed here: #2809695: Detect and install new dependencies on imports.

The issue can also occur without a new module dependency, when for example a field is added to one already enabled module and a corresponding field storage to another.

And the problem of unmet config dependencies can occur within a single module, if, for example, a field is added to a given module at the same time as a corresponding field storage.

All of these dependency handling issues are familiar in the context of configuration staging. That's why, rather than trying to address them again, in Configuration synchronizer I repurpose core's configuration staging to work with extension-provided config.

mpotter’s picture

The "Revert" code in config_update seems based on the code in core ConfigInstaller::createConfiguration(). This code *does* handle dependencies and also handles creating new config. I have created this issue: #2852626: Can we make ConfigInstaller::createConfiguration() Public? to see if we can make createConfiguration public so it can be called by config_update or by Features directly.

kclarkson’s picture

I running into a similar issue and was wondering if anybody had a solution or a best practices to avoid this issue?

In my case I cannot even enable any of my features because of this message.

mpotter’s picture

Until this is fixed you have to revert/import any dependencies first. For example, you need to import your field Storage before you can import your field Instance. If you put both of those into the same module then you might need to split the module into two temporarily.

However, we should have this fixed in Features within another week or two.

mpotter’s picture

Status: Active » Fixed
keesje’s picture

Woop!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

mikemadison’s picture

This seems to still be an issue using both the stable 3.5 and dev version that are live now. I'm still getting failures during the importing of features that have dependencies elsewhere... specifically in this case the feature defines an entire content type as its dependency (and that content type is stored in the same feature as the view) but the feature import is failing because the title field doesn't exist for that content type. I'm wondering if the view import is attempting to run prior to the rest of the content type coming in?

exception 'Exception' with feature_1 'No entity type for field title on view blocks' in                                                               [error]
/docroot/core/modules/views/src/Plugin/views/HandlerBase.php:697
Stack trace:
#0 /docroot/core/modules/views/src/Plugin/views/field/Field.php(793): Drupal\views\Plugin\views\HandlerBase->getEntityType()
#1 /docroot/core/modules/views/src/Plugin/views/field/Field.php(1010): Drupal\views\Plugin\views\field\Field->getEntityFieldRenderer()
#2 /docroot/core/lib/Drupal/Core/Cache/CacheableMetadata.php(171): Drupal\views\Plugin\views\field\Field->getCacheContexts()
#3 /docroot/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php(2288):
Drupal\Core\Cache\CacheableMetadata::createFromObject(Object(Drupal\views\Plugin\views\field\Field))
#4 /docroot/core/modules/views/src/Entity/View.php(326): Drupal\views\Plugin\views\display\DisplayPluginBase->calculateCacheMetadata()
#5 /docroot/core/modules/views/src/Entity/View.php(300): Drupal\views\Entity\View->addCacheMetadata()
#6 /docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(434):
Drupal\views\Entity\View->preSave(Object(Drupal\Core\Config\Entity\ConfigEntityStorage))
#7 /docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(389):
Drupal\Core\Entity\EntityStorageBase->doPreSave(Object(Drupal\views\Entity\View))
#8 /docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php(259):
Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\views\Entity\View))
#9 /docroot/core/lib/Drupal/Core/Entity/Entity.php(364):
Drupal\Core\Config\Entity\ConfigEntityStorage->save(Object(Drupal\views\Entity\View))
#10 /docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php(637): Drupal\Core\Entity\Entity->save()
#11 /docroot/core/lib/Drupal/Core/Config/ConfigInstaller.php(321): Drupal\Core\Config\Entity\ConfigEntityBase->save()
#12 /docroot/modules/contrib/features/src/FeaturesConfigInstaller.php(106): Drupal\Core\Config\ConfigInstaller->createConfiguration('',
Array)
#13 /docroot/modules/contrib/features/src/FeaturesManager.php(1357): Drupal\features\FeaturesConfigInstaller->createConfiguration('',
Array)
#14 /docroot/modules/contrib/features/drush/features.drush.inc(659): Drupal\features\FeaturesManager->createConfiguration(Array)
#15 [internal function]: drush_features_import('lightning_layou...', 'lightning_media', 'lightning_media...', 'lightning_media...', 'lightning_media...',
'lightning_media...', 'lightning_workf...', 'feature_1', 'feature_2', 'feature_3', 'feature_...', 'feature_5', 'feature_6',
'user')
#16 /docroot/modules/contrib/features/drush/features.drush.inc(289): call_user_func_array('drush_features_...', Array)
#17 [internal function]: drush_features_import_all()
#18 /vendor/drush/drush/includes/command.inc(422): call_user_func_array('drush_features_...', Array)
#19 /vendor/drush/drush/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#20 [internal function]: drush_command()
#21 /vendor/drush/drush/includes/command.inc(199): call_user_func_array('drush_command', Array)
#22 /vendor/drush/drush/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#23 /vendor/drush/drush/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#24 /vendor/drush/drush/drush.php(12): drush_main()
#25 {main}