Come correggere l'errore "non-existent config entity name returned by FieldStorageConfigInterface::getBundles()"
Tags: drupal, fix, italian
Published: 2024-06-16 17:02:33

Fonte: [How to fix "non-existent config entity name returned by FieldStorageConfigInterface::getBundles()"](https://www.drupal.org/project/drupal/issues/2916266)

Personalmente mi sono imbattuto in questo errore dopo aver aggiornato un sito storico che è nato con Drupal 8, è passato alla versione 9 e adesso ha affrontato l'aggiornamento a Drupal 10.

Nel corso degli anni il sito ha subito numerose aggiunte, modifiche e cancellazione di campi, ogni volta portandosi dietro molta "sporcizia".

Con l'aggiornamento a Drupal 10 ho notato una mole di errori nei log immensa quindi è stato necessario affrontare la problematica cercando.

Grazie alla community sono riuscito a trovare la soluzione citata nel link in cima al post.
Voglio riportare la soluzione per rendere più facile trovare la risposta perchè il post originale è diventato molto lungo e un po' dispersivo.

Per risolvere l'errore ci sono diversi modi:
* Utilizzando un `HOOK_update`:
```php
function YOURMODULENAME_update_10001() {
  ## Fixes:
  ## A non-existent config entity name returned by FieldStorageConfigInterface::getBundles(): entity type: paragraph, bundle: text, field name: field_image
  $entity_type = 'paragraph';
  $bundle = 'text';
  $field_name = 'field_image';

  /** @var \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory */
  $key_value_factory = \Drupal::service('keyvalue');
  $field_map_kv_store = $key_value_factory->get('entity.definitions.bundle_field_map');
  $map = $field_map_kv_store->get($entity_type);
  // Remove the field_dates field from the bundle field map for the page bundle.
  unset($map[$field_name]['bundles'][$bundle]);
  // Remove field definition if empty.
  if (empty($map[$field_name]['bundles'])) {
    unset($map[$field_name]);
  }

  $field_map_kv_store->set($entity_type, $map);
  
  // Remove entity type definition if empty after unsetting.
  if (empty($field_map_kv_store->get($entity_type))) {
    $field_map_kv_store->delete($entity_type);
  }
}
```
Nel codice precedente viene mostrato come esempio un errore sull'entità di tipo `paragraph`, sul bundle `text` dove il campo che causa il problema è `field_image`.
In questo modo si pulisce la definizione del campo `field_image` togliendo il suo riferimento al bundle `text` e se alla fine della pulizia se il campo non ha altri bundle al suo interno si procede all'eliminazione del campo stesso.
Proseguendo con la stessa logica se alla conclusione anche il tipo di entità è vuoto allora procediamo alla sua cancellazione.

Se l'errore è presente su più di un campo si può tranquillamente inserire la funzione in un `foreach` dove cambiando i parametri `$entity_type`, `$bundle` e `$field_name`.

* Creando un modulo personalizzato:  

  1 - Incomincia creando una cartella chiamato nel modo che preferisci, userò il placeholder `[MY_MODULE]` per indicare il nome del modulo.  

  2 - All'interno della cartella, crea un file con nome `[MY_MODULE].info.yml` e il suo contenuto dovrà essere:
  ```yaml
name: My Module
description: Fixes Error - A non-existent config entity name returned by FieldStorageConfigInterface::getBundles().
package: Custom
type: module
core_version_requirement: ^9.4 || ^10
  ```
  3 - Crea un altro file chiamato `drush.services.yml` e inserisci dentro questo codice:
```yaml
services:
  update.commands:
    class: \Drupal\[MY_MODULE]\Commands\UpdateCommands
    arguments:
      - '@keyvalue'
    tags:
      - { name: drush.command }
```
  4 - Crea una cartella `src`, dentro la quale crea un'altra cartella `Commands`.  
  5 - All'interno della cartella `Commands`, crea il file `UpdateCommands.php` e inserisci al suo interno questo codice:
```php
<?php

namespace Drupal\[MY_MODULE]\Commands;

use Drush\Commands\DrushCommands;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;

/**
 * A Drush commandfile.
 *
 * In addition to this file, you need a drush.services.yml
 * in root of your module, and a composer.json file that provides the name
 * of the services file to use.
 *
 * See these files for an example of injecting Drupal services:
 *   - http://git.drupalcode.org/devel/tree/src/Commands/DevelCommands.php
 *   - http://git.drupalcode.org/devel/tree/drush.services.yml
 */
class UpdateCommands extends DrushCommands {

  /**
   * The key value store to use.
   *
   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
   */
  protected $keyValueStore;

  /**
   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $key_value_factory
   *   The key value store to use.
   */
  public function __construct(KeyValueFactoryInterface $key_value_factory) {
    $this->keyValueStore = $key_value_factory;
  }

  /**
   * Corrects a field storage configuration. See https://www.drupal.org/project/drupal/issues/2916266 for more info
   *
   * @command update:correct-field-config-storage
   *
   * @param string $entity_type
   *   Entity type
   * @param string $bundle
   *   Bundle name
   * @param string $field_name
   *   Field name
   */
  public function correctFieldStorageConfig($entity_type, $bundle, $field_name) {
    $field_map_kv_store = $this->keyValueStore->get('entity.definitions.bundle_field_map');
    $map = $field_map_kv_store->get($entity_type);
    unset($map[$field_name]['bundles'][$bundle]);

    // Remove field definition if empty.
    if (empty($map[$field_name]['bundles'])) {
      unset($map[$field_name]);
    }

    $field_map_kv_store->set($entity_type, $map);
  
    // Remove entity type definition if empty after unsetting.
    if (empty($field_map_kv_store->get($entity_type))) {
      $field_map_kv_store->delete($entity_type);
    }
  }
}
```
  6 - Inserisci il modulo nella cartella `web/modules/custom/` del tuo sito, attivalo da interfaccia grafica o con `drush en [MY_MODULE]`.  
  7 - Adesso puoi usare il comando drush custom che è stato appena creato con `drush update:correct-field-config-storage [ENTITY_TYPE] [BUNDLE] [FIELD_NAME]`. Usando l'esempio di prima otterremmo questo comando `drush update:correct-field-config-storage paragraph text field_image`.  
  8 - Dopo aver seguito il comando l'errore dovrebbe essere scomparso e puoi disabilitare il modulo con `drush pmu [MY_MODULE]` e successivamente rimuoverlo.  


Un grande ringraziamento va alla community di Drupal che ha trovato la soluzione che ho leggermente modificato.