Config inspector stopped working after Drupal 10.2 update

Created on 25 January 2024, 11 months ago

Problem/Motivation

After updating Drupal core to 10.2.2, config inspector throws exception.
Symfony\Component\Validator\Exception\UnexpectedTypeException: Expected argument of type "array", "null" given in Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraintValidator->validate() (line 23 of /app/docroot/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidKeysConstraintValidator.php).
after debbuging, I can see that problem is with all search api solr configs. I don't know if problem is with solr configs or config inspector should catch this exception but:

  /**
   * Check schema compliance in configuration object.
   *
   * @param string $config_name
   *   Configuration name.
   *
   * @return array|bool
   *   FALSE if no schema found. List of errors if any found. TRUE if fully
   *   valid.
   *
   * @throws \Drupal\Core\Config\Schema\SchemaIncompleteException
   */
  public function validateValues($config_name): ConstraintViolationListInterface {
    if ($this->checkValues($config_name) === FALSE) {
      throw new \LogicException("$config_name has no config schema.");
    }

    $config_data = $this->configFactory->get($config_name)->get();
    $definition = $this->typedConfigManager->getDefinition($config_name);
    $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $config_data);
    $typed_config = $this->typedConfigManager->create($data_definition, $config_data, $config_name);
    // @todo Remove the preceding 3 lines in favor of th line below once this never is used to analyze Drupal before https://www.drupal.org/node/3360991.
    // phpcs:disable
    //$typed_config = $this->typedConfigManager->createFromNameAndData($config_name, $config_data);
    // phpcs:enable
      $violations = $typed_config->validate();
      return $violations;
  }

adnotation says it might be an array or bool but returned type is only ConstraintViolationListInterface.

  /**
   * Check schema compliance in configuration object.
   *
   * @param string $config_name
   *   Configuration name.
   *
   * @return array|bool
   *   FALSE if no schema found. List of errors if any found. TRUE if fully
   *   valid.
   */
  public function validateValues($config_name): ConstraintViolationListInterface|bool {
    if ($this->checkValues($config_name) === FALSE) {
      throw new \LogicException("$config_name has no config schema.");
    }

    $config_data = $this->configFactory->get($config_name)->get();
    $definition = $this->typedConfigManager->getDefinition($config_name);
    $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $config_data);
    $typed_config = $this->typedConfigManager->create($data_definition, $config_data, $config_name);
    // @todo Remove the preceding 3 lines in favor of th line below once this never is used to analyze Drupal before https://www.drupal.org/node/3360991.
    // phpcs:disable
    //$typed_config = $this->typedConfigManager->createFromNameAndData($config_name, $config_data);
    // phpcs:enable
    try {
      $violations = $typed_config->validate();
      return $violations;
    }
    catch (\Exception $e) {
      return FALSE;
    }
  }

and then we need additional work in controller to process empty violations.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Active

Version

2.1

Component

Code

Created by

πŸ‡΅πŸ‡±Poland lamp5 Rzeszow

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

Merge Requests

Comments & Activities

  • Issue created by @lamp5
  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    +1

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Maybe there is an issue with search_api config?

  • πŸ‡΅πŸ‡±Poland lamp5 Rzeszow

    Do you have any suggestions ?

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Well the it seems there is an expectation here that the schema is of a certain type/format/structure.

    I am thinking either that assumption is either wrong here. or, search_api has implemented their config schema incorrectly.

  • πŸ‡­πŸ‡ΊHungary GΓ‘bor Hojtsy Hungary

    Looks like the error is in core's code path. Not sure how we could pre-validate the schema so core does not fail this way. It is definitely a mismatch between core's understanding of how schema should be and the schema provided by your contrib module. But this does not look like the fault of config schema, rather the schema as applied when validating a config item.

    If the exception is thrown all the way forward to the config inspector level, the inspector may be able to catch it. Is that the case?

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    function looks like this:

      /**
       * Check schema compliance in configuration object.
       *
       * @param string $config_name
       *   Configuration name.
       *
       * @return array|bool
       *   FALSE if no schema found. List of errors if any found. TRUE if fully
       *   valid.
       *
       * @throws \Drupal\Core\Config\Schema\SchemaIncompleteException
       */
      public function validateValues($config_name): ConstraintViolationListInterface {
        if ($this->checkValues($config_name) === FALSE) {
          throw new \LogicException("$config_name has no config schema.");
        }
    
        $config_data = $this->configFactory->get($config_name)->get();
        $definition = $this->typedConfigManager->getDefinition($config_name);
        $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $config_data);
        $typed_config = $this->typedConfigManager->create($data_definition, $config_data, $config_name);
        // @todo Remove the preceding 3 lines in favor of th line below once this never is used to analyze Drupal before https://www.drupal.org/node/3360991.
        // phpcs:disable
        //$typed_config = $this->typedConfigManager->createFromNameAndData($config_name, $config_data);
        // phpcs:enable
        $violations = $typed_config->validate();
        return $violations;
      }

    So looks like it is failing here

        $violations = $typed_config->validate();
    

    ok, so we also have this issue which appears to have been closed now.

    https://www.drupal.org/node/3360991 β†’

    So looks like that could be updated now. Not sure if that will make a difference here?

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    uploaded pic that shows that it seems to be validating all values. Seems to be tripping up here

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Difficult to see what is breaking. Here are two configs that appear to break

    langcode: en
    status: true
    dependencies:
      module:
        - search_api_solr
    id: cache_document_default_7_0_0
    label: 'Document Cache'
    minimum_solr_version: 7.0.0
    environments: {}
    cache:
      name: document
      class: solr.LRUCache
      size: 512
      initialSize: 512
      autowarmCount: 0
    

    and

    id: rss_flickr_picture
    label: 'StreathamLife - Flickr picture feed'
    migration_group: rss
    status: true
    migration_tags:
      - rss feed media
    
    source:
      plugin: url
      data_fetcher_plugin: http
      data_parser_plugin: simple_xml
      urls: 'https://api.flickr.com/services/feeds/photos_public.gne?tags=streatham&format=rss_200'
    
      item_selector: /rss/channel/item
      fields:
        -
          name: guid
          label: GUID
          selector: guid
        -
          name: author
          label: Author
          selector: author
        -
          name: title
          label: Title
          selector: title
        -
          name: pub_date
          label: 'Publication date'
          selector: pubDate
        -
          name: summary
          label: Summary
          selector: description
        -
          name: image
          label: Image
          selector: 'media:content/@url'
        - 
          name: height
          label: Height
          selector: 'media:content/@height'
        - 
          name: width
          label: Width
          selector: 'media:content/@width'
        -
          name: thumbnail
          label: Thumbnail
          selector: 'media:thumbnail/@url'
    
      ids:
        guid:
          type: string
    
    process:
      field_title: title
      field_media_image:
        -
          plugin: skip_on_empty
          method: row
          source: image
          message: 'Field image is missing'
        -
          plugin: file_remote_image
          width: width
          height: height
          alt: title
          title: title
      created:
        plugin: format_date
        from_format: 'D, d M Y H:i:s O'
        to_format: 'U'
        source: pub_date
      uid:
        plugin: default_value
        default_value: 1
      status:
        plugin: default_value
        default_value: 1
    
    destination:
      plugin: 'entity:media'
      default_bundle: remote_image
    
  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    https://www.drupal.org/project/search_api_solr/issues/3415861 πŸ› ValidKeysConstraintValidator thrown by config inspector Active

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Ok reading up on this it seems that one solution is to disable this change that exposes the validation errors. https://www.drupal.org/project/config_inspector/issues/3359418 πŸ“Œ Expose validation constraint violations in Config Inspector UI and drush command Fixed

    Perhaps there is an issue in core with ValidKeysConstraintValidator?

    class ValidKeysConstraintValidator extends ConstraintValidator {
    
      /**
       * {@inheritdoc}
       */
      public function validate(mixed $value, Constraint $constraint) {
        assert($constraint instanceof ValidKeysConstraint);
    
        if (!is_array($value)) {
          throw new UnexpectedTypeException($value, 'array');
        }

    Certain values are expected are set as null, but ValidKeysConstraintValidator is expecting it to be an array?

    Not sure if there is an issue for this?

    I am not sure why UnexpectedTypeException is thrown here as well, as it seems reasonable that a key value can be set to null without throwing an exception?

  • πŸ‡·πŸ‡΄Romania claudiu.cristea Arad πŸ‡·πŸ‡΄

    I'm getting this for a null value of a mapping which is nullable. Maybe we need πŸ“Œ Configuration schema & required values: add test coverage for `nullable: true` validation support Fixed in Drupal 10.2?

  • πŸ‡¨πŸ‡¦Canada megan_m

    Applying the patch for issue #3364109 linked in the previous comment resolves this error for me.

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    @megan_m which patch and which version of Drupal?

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    OK @alexpott states on slack.

    I think config inspector should not have made changes that assume this code is present.

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Config inspector has also been updated see

    https://git.drupalcode.org/project/config_inspector/-/commit/6799e12839f...

    It seems plausible that this change has broken config inspector when running in 10.2.x or later

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    Updating as it appears latest update break config_inspector compatibility with 10.x

    see

    https://www.drupal.org/project/drupal/issues/3364109#comment-15504971 πŸ“Œ Configuration schema & required values: add test coverage for `nullable: true` validation support Fixed

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    My guess is this can be merged into 11.x release and we can probably revert for 10.x compatibility

  • Assigned to wim leers
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    I made Config Inspector compatible with Drupal 10.2 in πŸ“Œ Make tests pass on Drupal 10.2 Fixed .

    Investigating… πŸ•΅οΈ

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Linking the issues that @2dareis2do has mentioned.

    #16: Yes, https://git.drupalcode.org/project/config_inspector/-/commit/6799e12839f... landed for Config Inspector 2.1.8 β€” that's the commit for the issue I linked in my previous comment.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Well … the issue title is very broad, but AFAICT this has only ever been reported or reproduced for search_api_solr config, and even then only for migrated-from-Drupal 7 config for that module? πŸ˜…

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
    1. Installed Drupal core 10.2.4
    2. Installed latest Config Inspector, all is well.
    3. Installed search_api 1.32, all is still well.
    4. Installed search_api_solr tip of the 4.x branch, currently b9608ac764efa3df72a90e8102712ce3c36c3a17. BTW, this includes the following scary message: after installation 🫣
    5. Crash reproduced in Config Inspector UI at /admin/reports/config-inspectorπŸ‘:
      The website encountered an unexpected error. Try again later.
      
      Symfony\Component\Validator\Exception\UnexpectedTypeException: Expected argument of type "array", "null" given in Drupal\Core\Validation\Plugin\Validation\Constraint\ValidKeysConstraintValidator->validate() (line 23 of core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/ValidKeysConstraintValidator.php).
      Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateConstraints(NULL, '000000000000208e0000000000000000', Array) (Line: 154)
      Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode(Object) (Line: 164)
      Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode(Object, Array, 1) (Line: 106)
      Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validate(Object, NULL, NULL) (Line: 93)
      Drupal\Core\TypedData\Validation\RecursiveValidator->validate(Object) (Line: 132)
      Drupal\Core\TypedData\TypedData->validate() (Line: 352)
      Drupal\config_inspector\ConfigInspectorManager->validateValues('search_api_solr.solr_cache.cache_document_default_7_0_0') (Line: 176)
      Drupal\config_inspector\Controller\ConfigInspectorController->overview()
      call_user_func_array(Array, Array) (Line: 123)
      Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 627)
      Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
      Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
      Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
      Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
      Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
      Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
      Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
      Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
      Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 106)
      Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
      Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
      Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
      Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 36)
      Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 51)
      Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
      Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
      

    Repeating the same steps for Drupal 11 does not trigger a crash.

  • Status changed to Needs work 9 months ago
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Root cause analysis

    Part one: the "trigger"

    The "trigger" is

    search_api_solr.solr_cache.*:
      type: config_entity
      label: 'Solr Cache Config'
      mapping:
    …
        solr_configs:
          type: mapping
          nullable: true
    

    in config/schema/search_api_solr.cache.schema.yml

    Drupal core config schema infrastructure

    Drupal core introduced the ability to mark type: sequence as nullable in #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted β†’ . But … it implemented it at the ArrayElement level, which is the parent class of both Sequence (type: sequence) and Mapping (type: mapping).

    Not a single config schema in Drupal core specifies nullable: true for a type: mapping. So when </code> was introduced in ✨ Add validation constraints to config_entity.dependencies Fixed , that was overlooked. <code>10.1.0 was the first release in which it shipped.

    Subsequently, πŸ“Œ Configuration schema & required values: add test coverage for `nullable: true` validation support Fixed landed after 10.3.x and 11.x and it contains this:

          // If the value is NULL, then the `NotNull` constraint validator will
          // set the appropriate validation error message.
          // @see \Drupal\Core\Validation\Plugin\Validation\Constraint\NotNullConstraintValidator
          if ($value === NULL) {
            return;
          }
    

    … which is why @2dareis2do reported at #3415861-15: ValidKeysConstraintValidator thrown by config inspector β†’ that that "fixed" the problem.

    Conclusion

    • This is not a bug in Config Inspector; it's just executing Drupal core's validation logic.
    • Drupal core evolved its validation infrastructure in 10.1 and subsequent releases, but does not apply it to any non-core config! Precisely because we knew that not all contrib config would be compliant/correctly use config schema … and because we knew that Drupal core's config validation infrastructure was not yet in a good enough place, we'll only be able to consider it ready for prime time once at a minimum all core config is validatable.
    • But in this particular case … the contrib module's "trigger" actually is valid config schema and is just triggering a bug/oversight in 10.1.x and 10.2.x!

    The only possible way forward is … to make Config Inspector "simulate" the part of the fix that πŸ“Œ Configuration schema & required values: add test coverage for `nullable: true` validation support Fixed landed, and which I quoted above. So I'll do that next πŸ€“ This will only be necessary for as long as this module supports Drupal <10.3.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update 9 months ago
    Not currently mergeable.
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update 9 months ago
    3 pass
  • Status changed to Needs review 9 months ago
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update 9 months ago
    3 pass
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update 9 months ago
    3 pass
  • Issue was unassigned.
  • Status changed to RTBC 9 months ago
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί
  • Status changed to Fixed 9 months ago
  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    Hah, looks like @claudiu.cristea caught the root cause 2 weeks ago in #12. I wish you had renamed the issue title, @claudiu.cristea, then your crucial single line would've been lost in this ocean of long comments that only talked about symptoms πŸ˜„ Either way, fixed now β€” will get a release out shortly.

  • πŸ‡¬πŸ‡§United Kingdom 2dareis2do

    thanks @Wim Leers.

  • πŸ‡§πŸ‡ͺBelgium wim leers Ghent πŸ‡§πŸ‡ͺπŸ‡ͺπŸ‡Ί

    fyi iirc I also had similar with migrate yaml config and not specifying enforced dependencies.

    That must've been with the migrate_plus module then, because Drupal core's migration system is completely independent of the configuration system.

    Did the commit above fix that too? I'd appreciate it if you could test + confirm that :) (A quick scan of https://git.drupalcode.org/project/migrate_plus/-/tree/6.0.x/config/sche... reveals no occurrences of nullable: true, so it seems that's an unrelated problem. If you can still reproduce that problem, could you please create a new/separate issue for that? πŸ™)

  • Automatically closed - issue fixed for 2 weeks with no activity.

  • πŸ‡³πŸ‡±Netherlands idebr

    @Wim Leers this issue was marked fixed but the merge request is still open. Could you merge it and tag a new release?

  • πŸ‡ΊπŸ‡ΈUnited States pdcarto

    Paging @Wim Leers - the issue branch has still not been merged (there is no MR).

Production build 0.71.5 2024