Configuration system doesn't allow importing a single item from a non-default collection

Created on 2 June 2016, over 8 years ago
Updated 19 January 2023, about 2 years ago

Problem/Motivation

Configuration system doesn't allow importing a single item from a non-default collection.

Given minimal Drupal installation with config and locale modules installed. Let's add new language (for instance Russian) and download its updates. Then go to admin/config/development/configuration/full/export and get full config archive or just run drush cex sync. In the produced config you will find a folder named language.ru (ru stands for Russian language in this example) where translated configs are placed.

Now try to import any single item back to active storage from this page admin/config/development/configuration/single/import or using drush cim sync --partial, ensure some config item(s) are modified for the default collection.
I will use this one as example:

system.maintenance.yml

message: '@site is currently under maintenance. We should be back shortly. Thank you for your patience!'
langcode: en

The following errors occur before confirmation step:

Notice: Undefined index: language.ru in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).

Warning: array_keys() expects parameter 1 to be array, null given in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).

After submitting the form - nothing changes in default collection and all items in the language.ru collection are broken (they could be empty or contain data from the default collection). It can be verified by exporting full config once again and compare with the original one.

This issue makes absolutely impossible to rely on config import/export system.

Steps to reproduce

Scenario 1.

  1. Install the latest Drupal 8.x using the standard profile.
  2. Add additional language at admin/config/regional/language/add.
  3. Export a single configuration item (eg. system.maintenance) at admin/config/development/configuration/single/export.
  4. Copy and paste item's content at admin/config/development/configuration/single/import
    Configuration type - Simple configuration;
    Configuration name - system.maintenance;
    Change config's message property somehow and click Import button.
  5. Confirm form submission.

Expected results: Changes are saved w/o errors.
Actual results: Changes not saved, errors displayed, all language.ru configs filled with data from default language settings:

Error message

Notice: Undefined index: language.ru in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).
Warning: array_keys() expects parameter 1 to be array, null given in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).
Notice: Undefined index: language.ru in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).
Warning: array_keys() expects parameter 1 to be array, null given in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).
Notice: Undefined index: language.ru in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).
Warning: array_keys() expects parameter 1 to be array, null given in Drupal\config\StorageReplaceDataWrapper->listAll() (line 131 of core/modules/config/src/StorageReplaceDataWrapper.php).

Scenario 2.

  1. Install the latest Drupal 8.x with minimal profile.
  2. Enable config and locale modules (drush en config locale)
  3. Add additional language at admin/config/regional/language/add.
  4. Run drush config-export sync to export current configs.
  5. Go to exported folder and make sure translations exist and have localized strings.
  6. Change any item's text (Eg. in the system.maintenance.yml)
  7. Run drush config-import sync --partial to update active config.
  8. Run drush config-export sync to export configs again and see the differences.

Expected results: The active configuration is identical to the configuration in the export directory.
Actual results: Changes to default collection not saved, non-default collection items overriden by data from default collection corresponding items, errors displayed:

$ drush config-import sync --partial
Collection Config Operation
system.maintenance update
Import the listed configuration changes? (y/n): y
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
The configuration was imported successfully. [success]

Scenario 3. (Thanks to @Arla for idea given in #7)

  1. Install the latest Drupal 8.x with standard profile.
  2. Add additional language at admin/config/regional/language/add.
  3. Run drush config-edit system.maintenance, edit and save changes.

Expected results: Changes are saved w/o errors.
Actual results: Changes not saved and errors displayed:

$ drush config-edit system.maintenance

Collection Config Operation
system.maintenance update
Import the listed configuration changes? (y/n): y
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
array_keys() expects parameter 1 to be array, null given StorageReplaceDataWrapper.php:131 [warning]
The configuration was imported successfully. [success]

Note: If you get errors like this (Not reproducable prior to core 8.3.x):

Drupal\Core\Config\ConfigImporterException: There were errors validating the config synchronization. in [error]
Drupal\Core\Config\ConfigImporter->validate() (line 728 of core/lib/Drupal/Core/Config/ConfigImporter.php).
The import failed due for the following reasons: [error]
Site UUID in source storage does not match the target storage.

You should sync system.site uuid between collections using sql query or shell command:

	$ head -n1 PATH_TO_SYNC/system.site.yml >> PATH_TO_SYNC/language/YOUR_LANGUAGE/system.site.yml 
	$ drush config-import sync -y

Proposed resolution

Fix createCollection method of StorageReplaceDataWrapper class to valid object with correct collection.

Remaining tasks

Find out a way to allow importing of the config items from any collection using UI and drush cim.

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Fixed

Version

8.1 ⚰️

Component
ConfigΒ  β†’

Last updated 17 days ago

Created by

πŸ‡²πŸ‡©Moldova VitalyM

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • leymannx Berlin

    Voting to reopen. Or do we create a new issue instead?

  • πŸ‡·πŸ‡ΈSerbia holo96

    Facing same Issue in 10.1.4
    Yes, I guess someone should reopen issue

  • πŸ‡©πŸ‡ͺGermany stefan.korn Jossgrund

    The partial import still does not respect translations.

    It is discussed here too: https://github.com/drush-ops/drush/issues/2069

    --partial uses a very low level API and apparently bypasses a lot of the config event system ...

    This is probably the reason why translations are not imported with partial.

    As far as I can see, there is also no way to import a single translation config yml (yml from configdir/language/langcode/) within the backend at admin/config/development/configuration, which also points in the direction that "partial" import will not work with translations.

    There is also given a workaround in the discussion mentioned above:

    config-export into a temp dir
    copy the contents of the --partial dir into the temp dir
    config-import from the temp dir

Production build 0.71.5 2024