When you do a config-import, config entities (like features_bundles) are created only after modules are installed. So if a config-import installs both features and a feature module, at the time it's installing the feature module no features_bundles yet exist, including the default one. When features attempts to auto-create the bundle for the feature module, it wants to base it on the default bundle, but no such bundle exists and it dies.
I'm not really sure what the best fix is. The easiest thing is to just disable features auto-creation if a config-import is in progress (using ConfigInstallerInterface::isSyncing()). Alternatively, we could keep auto-creation but base the new bundle on something else if no default bundle exists yet.
To reproduce:
* Install Drupal: drush site-install -y
* Enable features_ui: drush en -y features_ui
* Create a new features bundle "mybundle" by visiting admin/config/development/features/bundle . Save the bundle.
* Export the "Article" content type as a feature, with the new bundle:
drupal$ drush features-export --bundle=mybundle article
Package Article written to modules/custom/mybundle_article.
* Enable the new module: drush en -y mybundle_article
* Export your configuration: drush config-export -y sync
* Remove features and the new feature: drush pmu -y mybundle_article; drush pmu -y features_ui; drush pmu -y features
* Attempt to revert to the earlier config, but it dies:
drupal$ drush config-import -y sync
Collection Config Operation
features.bundle.default create
features.bundle.mybundle create
features.settings create
core.extension update
Import the listed configuration changes? (y/n): y
PHP Fatal error: Call to a member function createDuplicate() on a non-object in /Users/vasi/Sites/devdesktop/drupal8/modules/contrib/features/src/FeaturesAssigner.php on line 276
PHP Stack trace:
PHP 1. {main}() /Applications/DevDesktop/drush/vendor/drush/drush/drush.php:0
PHP 2. drush_main() /Applications/DevDesktop/drush/vendor/drush/drush/drush.php:12
PHP 3. Drush\Boot\BaseBoot->bootstrap_and_dispatch() /Applications/DevDesktop/drush/vendor/drush/drush/includes/preflight.inc:64
PHP 4. drush_dispatch() /Applications/DevDesktop/drush/vendor/drush/drush/lib/Drush/Boot/BaseBoot.php:65
PHP 5. call_user_func_array:{/Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:183}() /Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:183
PHP 6. drush_command() /Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:183
PHP 7. _drush_invoke_hooks() /Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:215
PHP 8. call_user_func_array:{/Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:364}() /Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:364
PHP 9. drush_config_import() /Applications/DevDesktop/drush/vendor/drush/drush/includes/command.inc:364
PHP 10. drush_op() /Applications/DevDesktop/drush/vendor/drush/drush/commands/core/config.drush.inc:640
PHP 11. drush_call_user_func_array() /Applications/DevDesktop/drush/vendor/drush/drush/includes/drush.inc:706
PHP 12. _drush_config_import() /Applications/DevDesktop/drush/vendor/drush/drush/includes/drush.inc:720
PHP 13. Drupal\Core\Config\ConfigImporter->import() /Applications/DevDesktop/drush/vendor/drush/drush/commands/core/config.drush.inc:662
PHP 14. Drupal\Core\Config\ConfigImporter->doSyncStep() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Config/ConfigImporter.php:469
PHP 15. Drupal\Core\Config\ConfigImporter->processExtensions() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Config/ConfigImporter.php:492
PHP 16. Drupal\Core\Config\ConfigImporter->processExtension() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Config/ConfigImporter.php:553
PHP 17. Drupal\Core\ProxyClass\Extension\ModuleInstaller->install() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Config/ConfigImporter.php:789
PHP 18. Drupal\Core\Extension\ModuleInstaller->install() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php:87
PHP 19. Drupal\Core\Extension\ModuleHandler->invokeAll() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Extension/ModuleInstaller.php:298
PHP 20. call_user_func_array:{/Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Extension/ModuleHandler.php:393}() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Extension/ModuleHandler.php:393
PHP 21. features_modules_installed() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Core/Extension/ModuleHandler.php:393
PHP 22. Drupal::service() /Users/vasi/Sites/devdesktop/drupal8/modules/contrib/features/features.module:44
PHP 23. Drupal\Component\DependencyInjection\Container->get() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal.php:158
PHP 24. Drupal\Component\DependencyInjection\Container->createService() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Component/DependencyInjection/Container.php:181
PHP 25. Drupal\features\FeaturesAssigner->__construct() /Users/vasi/Sites/devdesktop/drupal8/core/lib/Drupal/Component/DependencyInjection/Container.php:281
PHP 26. Drupal\features\FeaturesAssigner->createBundlesFromPackages() /Users/vasi/Sites/devdesktop/drupal8/modules/contrib/features/src/FeaturesAssigner.php:94
PHP 27. Drupal\features\FeaturesAssigner->createBundleFromDefault() /Users/vasi/Sites/devdesktop/drupal8/modules/contrib/features/src/FeaturesAssigner.php:337
| Comment | File | Size | Author |
|---|---|---|---|
| #10 | 2674792-10.patch | 5.34 KB | vasi |
| #7 | interdiff.txt | 2.34 KB | vasi |
| #7 | 2674792-7.patch | 8.33 KB | vasi |
| #3 | 2674792-auto-create-import.patch | 4.45 KB | vasi |
Comments
Comment #2
nedjoThanks for your detailed explanation of the problem.
We could read directly from the file storage (config/features.bundle.default.yml) rather than duplicating the existing bundle, but I believe the current approach is by design in that a new bundle should inherit any customizations made to the default bundle.
So, possibly, test for the default bundle and, if not found, load from the file storage?
Comment #3
vasi commentedOk, here's an attempt at that.
Comment #4
vasi commentedComment #5
nedjoLooking good! A couple of suggestions:
We should inject the entity type manager service so we can use it here.
We should leave these lines out. See #2668526: Do not export _core default_config_hash.
Comment #6
nedjoComment #7
vasi commentedOh, it looks like we already have entityManager, we just don't declare it.
Fixed the two issues identified in #5.
Tests are expected to fail, due to a missing file in this commit: https://www.drupal.org/node/2666836#comment-10997991 .
Comment #9
mpotter commentedHmm, looks like there is some extra stuff in the patch in #7, like the ForwardDependency patch and some other files.
Also, just a quick dumb question...can we just add a config dependency of features.bundle.default to the features.bundle.mybundle config? Would that let Drupal install the default bundle before any other bundles?
Comment #10
vasi commentedSorry about the bad patch, this one should be fixed.
I don't think any sort of dependencies between bundles would help. At the time that we are auto-creating a bundle, we don't actually have a full config for the bundle—hence the "auto-creation". Also, we don't have any bundles in config at that point.
Comment #11
mpotter commentedThis looks good to me.
Comment #13
mpotter commentedCommitted to bf93ecd and 8ddce1e