Mismatched entity and/or field definitions after update from 1.6 to 2.0-rc2

Created on 18 March 2019, almost 6 years ago
Updated 4 August 2023, over 1 year ago

After an upgrade from 1.6 => 2.0-rc2 I'm left with the mentioned error message on the status page.

Errors found
Entity/field definitions

Mismatched entity and/or field definitions
The following changes were detected in the entity type and field definitions.

drush entup gives the following exception:

>  [warning] array_intersect_key(): Argument #1 is not an array SqlContentEntityStorageSchema.php:2212
>  [error]  Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException: The SQL storage cannot change the schema for an existing field (field_runnin in node entity) with data. in Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->updateDedicatedTableSchema() (line 1493 of D\core\lib\Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema.php).

In ProcessBase.php line 184:

  Unable to decode output into JSON.

I did the upgrade using composer and afterwards:

$ drush updb
 ---------------- ----------- --------------- ------------------------------------------------------------------------
  Module           Update ID   Type            Description
 ---------------- ----------- --------------- ------------------------------------------------------------------------
  duration_field   8200        hook_update_n   Implements hook_update_N().   Updates module from 8.x-1.x to 8.x-2.x.
 ---------------- ----------- --------------- ------------------------------------------------------------------------


 Do you wish to run the specified pending updates? (yes/no) [yes]:
>  

>  [notice] Update started: duration_field_update_8200
>  [notice] Update completed: duration_field_update_8200
 [success] Finished performing updates.

$ drush cr 
 [success] Cache rebuild complete.

Entities with the duration_field seem to work alright so far.

🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇳🇱Netherlands spokje

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.

  • I'm not sure if the issue I ran into today has the exact same cause; but the error messages/behaviour led me to this issue.

    In my case, the status report showed that two fields required updates:

    Entity/field definitions
    Mismatched entity and/or field definitions
    The following changes were detected in the entity type and field definitions.
    Content

    The node.field_duration field needs to be updated.
    The node.workshop__duration field needs to be updated.

    Trying to save the field settings again, for these duration fields, would throw the SQL exception:

    TypeError: array_intersect_key(): Argument #1 ($array) must be of type array, null given in array_intersect_key() (line 2485 of /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php)

    #0 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(2485): array_intersect_key()
    #1 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(1755): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->hasColumnChanges()
    #2 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(1535): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->updateDedicatedTableSchema()
    #3 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php(703): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->performFieldSchemaOperation()
    #4 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1545): Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema->onFieldStorageDefinitionUpdate()
    #5 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1590): Drupal\Core\Entity\Sql\SqlContentEntityStorage->Drupal\Core\Entity\Sql\{closure}()
    #6 /srv/app/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(1548): Drupal\Core\Entity\Sql\SqlContentEntityStorage->wrapSchemaException()
    #7 /srv/app/core/lib/Drupal/Core/Field/FieldStorageDefinitionListener.php(104): Drupal\Core\Entity\Sql\SqlContentEntityStorage->onFieldStorageDefinitionUpdate()
    #8 /srv/app/core/modules/field/src/Entity/FieldStorageConfig.php(388): Drupal\Core\Field\FieldStorageDefinitionListener->onFieldStorageDefinitionUpdate()
    #9 /srv/app/core/modules/field/src/Entity/FieldStorageConfig.php(300): Drupal\field\Entity\FieldStorageConfig->preSaveUpdated()
    #10 /srv/app/core/lib/Drupal/Core/Entity/EntityStorageBase.php(562): Drupal\field\Entity\FieldStorageConfig->preSave()
    #11 /srv/app/core/lib/Drupal/Core/Entity/EntityStorageBase.php(517): Drupal\Core\Entity\EntityStorageBase->doPreSave()
    #12 /srv/app/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php(253): Drupal\Core\Entity\EntityStorageBase->save()
    #13 /srv/app/core/lib/Drupal/Core/Entity/EntityBase.php(339): Drupal\Core\Config\Entity\ConfigEntityStorage->save()
    #14 /srv/app/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php(608): Drupal\Core\Entity\EntityBase->save()
    #15 /srv/app/core/modules/field_ui/src/Form/FieldStorageConfigEditForm.php(229): Drupal\Core\Config\Entity\ConfigEntityBase->save()
    #16 [internal function]: Drupal\field_ui\Form\FieldStorageConfigEditForm->save()
    #17 /srv/app/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array()
    #18 /srv/app/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers()
    #19 /srv/app/core/lib/Drupal/Core/Form/FormBuilder.php(597): Drupal\Core\Form\FormSubmitter->doSubmitForm()
    #20 /srv/app/core/lib/Drupal/Core/Form/FormBuilder.php(325): Drupal\Core\Form\FormBuilder->processForm()
    #21 /srv/app/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm()
    #22 [internal function]: Drupal\Core\Controller\FormController->getContentResult()
    #23 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
    #24 /srv/app/core/lib/Drupal/Core/Render/Renderer.php(580): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
    #25 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext()
    #26 /srv/app/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
    #27 /srv/vendor/symfony/http-kernel/HttpKernel.php(169): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
    #28 /srv/vendor/symfony/http-kernel/HttpKernel.php(81): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
    #29 /srv/app/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle()
    #30 /srv/app/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
    #31 /srv/app/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
    #32 /srv/app/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
    #33 /srv/app/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
    #34 /srv/app/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
    #35 /srv/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
    #36 /srv/app/core/lib/Drupal/Core/DrupalKernel.php(718): Stack\StackedHttpKernel->handle()
    #37 /srv/app/index.php(18): Drupal\Core\DrupalKernel->handle()
    #38 {main}

    After a bunch of testing, I figured out that the issue is the stored entity storage schema; the database fields are 'correct', but this stored schema was not updated. The entity storage schema still listed a _value field, but no _duration or _seconds fields as with a newly added duration field.

    I'm not quite sure of the implications, but the _value field appears to be replaced by _duration and _seconds appears to have a simple value (although changing some settings might change that).

    In order to resolve my errors I created a script that updates the stored entity storage schema; it renames _value to _duration and adds _seconds with the values my newly created field contained. I am unsure if these values are now completely correct, but I am no longer seeing the warning in the status report and can save the field settings without errors. You can find my script in the form of a drush deploy hook below, but of course; use at your own risk and backup your database. You should only have to change the field names in $fields, the fields will be skipped if there is no _value defined.

    
    /**
     * Fix the stored duration storage schema to prevent SQL errors.
     */
    
    function MODULENAME_deploy_9000() {
      $fields = ['workshop__duration', 'field_duration'];
      $entities = ['node', 'node_revision'];
      $messages = [];
    
      $entity_storage_schema_sql = \Drupal::keyValue('entity.storage_schema.sql');
      foreach ($fields as $fieldname) {
        $definition = $entity_storage_schema_sql->get('node.field_schema_data.' . $fieldname, []);
        foreach ($entities as $entity) {
          if (!isset($definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value'])) {
            $messages[] = 'Skipping ' . $entity . ' field ' . $fieldname;
            continue;
          }
    
          $messages[] = 'Fixing ' . $entity . ' field ' . $fieldname;
          $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_duration'] = $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value'];
          unset($definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_value']);
    
          $definition[$entity . '__' . $fieldname]['fields'][$fieldname . '_seconds'] = [
            'type' => 'int',
            'size' => 'big',
            'not null' => FALSE,
          ];
        }
        $entity_storage_schema_sql->set('node.field_schema_data.' . $fieldname, $definition);
      }
    
      return implode(PHP_EOL, $messages);
    }
    
    
Production build 0.71.5 2024