Saving an existing field with a different UUID, including by attempting to import even an absolutely identical copy of the field that has a different UUID, puts a Drupal installation in an unrecoverable state.
- Install 8.x standard.
- Emulate a field machine name/UUID conflict by copying
field.field.field_tags.ymlfrom the active configuration directory to the staging directory.
- In the staging directory, change the
field.field.field_tags.ymlslightly, e.g. just change the first character.
admin/config/development/syncand click import.
- Your site is broken. There's no escape. Any and every page load will show:
Drupal\field\FieldException: Attempt to create an instance of unknown field old-config-uuid-here-nskjdfhisuhdfwf in Drupal\field\Plugin\Core\Entity\FieldInstance->__construct() (line 259 of /Applications/MAMP/htdocs/d8git/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php).
The website has encountered an error. Please try again later.
Note: This video also illustrates a related featurebug that is mostly just a minor WTF once this issue is resolved, which is that an exactly identical fresh installation has different UUIDs for all the same default configuration.
The reason the site is unrecoverably broken is that the exception is being thrown in a menu item access check:
- Standard and Minimal include a preconfigured instance of the Tools menu.
- Node adds
node/addto the Tools menu.
- The access callback for
createop for each type with a fake node object.
- If passed a fake node object,
entity_create()to make it into a proper Node entity.
entity_create()constructs the node bundle's field instance, which has a UUID that no longer matches the field UUID.
The field API should disallow changing the UUID of an existing field on save, since field instance data depends on this UUID.
- Consider moving the field UUID check out of
FieldInstance::save(), so that a data integrity issue does not completely break Drupal.
- Provide test coverage ensuring the proper exceptions are thrown, both with an API save and functionally via a config import.
|PASSED: [[SimpleTest]]: [MySQL] 58,072 pass(es).|
|PASSED: [[SimpleTest]]: [MySQL] 58,074 pass(es).|
|PASSED: [[SimpleTest]]: [MySQL] 57,865 pass(es).|