Problem/Motivation

We are upgrading Drupal to 9.3.4 and PHP to 8.x. We have recently upgraded to SOLR 7.

We were getting an ajax error when reindexing one of our Solr indexes, so we went into the index to see what was the matter. On the "Processors" page, we got the following whitescreen exception in the codeblock below. It seemed to be very upset about Ignore Characters.

We removed both Ignore Characters and Ignore Case from the configuration file and ran cim. The Processors page finally loaded (without any ignore characters or ignore case settings, of course) and we saw a note under Ignore Case:

> It is recommended not to use this processor with the selected server.

But this wasn't under Ignore Characters. I tried re-adding Ignore Characters through the UI and saved the Processors settings. I got flagged with a required field.

> You need to select at least one field for which to add hierarchy data.

I went into that tab below and selected a field. and saved the Pocessors settings again.

Warning: foreach() argument must be of type array|object, null given in Drupal\search_api\Plugin\search_api\processor\IgnoreCharacters->process() (line 126 of /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Plugin/search_api/processor/IgnoreCharacters.php)
#0 /mnt/www/html/oursitefoo/docroot/core/includes/bootstrap.inc(346): _drupal_error_handler_real(2, 'foreach() argum...', '/mnt/www/html/n...', 126)
#1 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Plugin/search_api/processor/IgnoreCharacters.php(126): _drupal_error_handler(2, 'foreach() argum...', '/mnt/www/html/n...', 126)
#2 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Processor/FieldsProcessorPluginBase.php(529): Drupal\search_api\Plugin\search_api\processor\IgnoreCharacters->process('the')
#3 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Processor/FieldsProcessorPluginBase.php(405): Drupal\search_api\Processor\FieldsProcessorPluginBase->processKey('the')
#4 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Processor/FieldsProcessorPluginBase.php(397): Drupal\search_api\Processor\FieldsProcessorPluginBase->processKeys('the')
#5 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Processor/FieldsProcessorPluginBase.php(308): Drupal\search_api\Processor\FieldsProcessorPluginBase->processKeys(Array)
#6 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Entity/Index.php(666): Drupal\search_api\Processor\FieldsProcessorPluginBase->preprocessSearchQuery(Object(Drupal\search_api\Query\Query))
#7 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Query/Query.php(582): Drupal\search_api\Entity\Index->preprocessSearchQuery(Object(Drupal\search_api\Query\Query))
#8 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Query/Query.php(532): Drupal\search_api\Query\Query->preExecute()
#9 /mnt/www/html/oursitefoo/docroot/profiles/custom/ourprofilefoo/modules/contrib/search_api/src/Plugin/views/query/SearchApiQuery.php(581): Drupal\search_api\Query\Query->execute()
#10 /mnt/www/html/oursitefoo/docroot/core/modules/views/src/ViewExecutable.php(1426): Drupal\search_api\Plugin\views\query\SearchApiQuery->execute(Object(Drupal\views\ViewExecutable))
#11 /mnt/www/html/oursitefoo/docroot/core/modules/views/src/ViewExecutable.php(1454): Drupal\views\ViewExecutable->execute(NULL)
#12 /mnt/www/html/oursitefoo/docroot/core/modules/views/src/Plugin/views/display/Page.php(199): Drupal\views\ViewExecutable->render()
#13 /mnt/www/html/oursitefoo/docroot/core/modules/views/src/ViewExecutable.php(1630): Drupal\views\Plugin\views\display\Page->execute()
#14 /mnt/www/html/oursitefoo/docroot/core/modules/views/src/Element/View.php(81): Drupal\views\ViewExecutable->executeDisplay('page_1', Array)
#15 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array)
#16 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(101): call_user_func_array(Array, Array)
#17 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/Renderer.php(772): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'exception', 'Drupal\\Core\\Ren...')
#18 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/Renderer.php(363): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array)
#19 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/Renderer.php(201): Drupal\Core\Render\Renderer->doRender(Array, false)
#20 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(241): Drupal\Core\Render\Renderer->render(Array, false)
#21 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/Renderer.php(564): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
#22 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(242): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#23 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(132): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#24 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#25 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#26 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(142): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#27 /mnt/www/html/oursitefoo/vendor/symfony/http-kernel/HttpKernel.php(163): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object(Symfony\Component\HttpKernel\Event\ViewEvent), 'kernel.view')
#28 /mnt/www/html/oursitefoo/vendor/symfony/http-kernel/HttpKernel.php(80): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#29 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#31 /mnt/www/html/oursitefoo/docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#32 /mnt/www/html/oursitefoo/docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#33 /mnt/www/html/oursitefoo/docroot/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#34 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#35 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#36 /mnt/www/html/oursitefoo/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#37 /mnt/www/html/oursitefoo/docroot/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#38 /mnt/www/html/oursitefoo/docroot/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#39 {main}

Proposed resolution

Updb should remove the Ignore Case from the index configuration for servers which shouldn't use them. If a heirarchy field is not selected when heirarchy is selected, then heirarchy should be removed from configuration by updb. I think this all stems from PHP8 being upset with null values in some situations.

Comments

loopy1492 created an issue. See original summary.

loopy1492’s picture

After fixing the ignore settings and also replacing A LOT of fields that were marked "fulltext" with just "string", I am getting no more errors on the Processor page. I have a new problem.

So now, when I go to the main index page at /admin/config/search/search-api/index/my_index, the # of items is cartoonishly low (400).

I see a message which says "Not all items have been tracked for this index. This means the displayed index status is incomplete and not all items will currently be indexed." And there's a "Track now" button.

When I click that button, I get redirected to a /batch?id=46651&op=start page with the following message

An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /batch?id=46651&op=do_nojs&op=do
StatusText: parsererror
ResponseText:

and the # of items in the number underneath "Index Status" does not increase at all. It stays at 400/400.

However, after messing around, I realized that, while on this /batch page, if I click the refresh button on my browser, I get a weird white and gray screen with only:

Processing
An error has occurred.
Please continue to the error page

And then if I go back to the index page, it shows an additional 200 items are ready for indexing.

I am extremely confused.

loopy1492’s picture

I have reason to believe that the AJAX issue is being caused by an unrelated module.
https://www.drupal.org/project/workbench_moderation/issues/3262995

I will see if I can't get this part fixed and then double back on this issue to see if it was the Processor settings, the fulltext indexing, or both that were causing the Processor page to fail. I won't know until I fix the unrelated issue.

loopy1492’s picture

Yes, the AJAX issue was unrelated, but the original `[warning] Invalid argument supplied for foreach() IgnoreCharacters.php:126` error still occurs whithout interference from the Workbench module. On investigation, that error happens on the command line when running sapi-i, but without PHP 8 upgraded, the Processors page does not error out.

My workaround is to downgrade to PHP 7, refactor the Ignore Characters, remove the Ignore Case, select a heirarchy data, and export the config, then re-enable PHP 8.

marlon.buella’s picture

Version: 8.x-1.23 » 8.x-1.24
StatusFileSize
new1.53 KB

I am able to fix the issue by wrapping the foreach block inside the following condition:

if ($this->configuration['ignorable_classes']) {
  // foreach (...) { ... }
}
marlon.buella’s picture

StatusFileSize
new1.52 KB

I am able to fix the issue by wrapping the foreach block inside the following condition:

if ($this->configuration['ignorable_classes']) {
  // foreach (...) { ... }
}
drunken monkey’s picture

Component: General code » Plugins
Status: Active » Fixed

Not quite sure what could cause the ignorable_classes option to be NULL, it should always be set to an array (potentially an empty one) as far as I can see. However, no harm in a tiny check, to be on the safe side.

Thanks for the patch, marlon.buella! I think we can be a bit more concise, but otherwise looks good.
Changed the check slightly and committed. Thanks again!

Status: Fixed » Closed (fixed)

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