Problem/Motivation
In PHP 8.3, strrpos() and strlen() have become more strict. In LeafletMap::getPopupContent(), when using #rendered_view_fields, the code passes a malformed render array or receives a NULL theme hook, leading to a cascade of errors. On large datasets (e.g., 25,000+ rows), this results in memory exhaustion due to the sheer volume of logs.
Two main errors occur:
Deprecated function: strrpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in Drupal\Core\Theme\ThemeManager->render()
TypeError: strlen(): Argument #1 ($string) must be of type string, array given in Drupal\Component\Utility\Unicode::strlen()
#1 [internal function]: _drupal_error_handler(8192, 'strrpos(): Pass...', '/var/www/html/w...', 168)
#2 /var/www/html/web/core/lib/Drupal/Core/Theme/ThemeManager.php(168): strrpos(NULL, '__')
#3 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(497): Drupal\Core\Theme\ThemeManager->render(NULL, Array)
#4 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(510): Drupal\Core\Render\Renderer->doRender(Array, Object(Drupal\Core\Render\RenderContext))
#5 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(250): Drupal\Core\Render\Renderer->doRender(Array, Object(Drupal\Core\Render\RenderContext))
#6 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(141): Drupal\Core\Render\Renderer->doRenderRoot(Array, Object(Drupal\Core\Render\RenderContext))
#7 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(627): Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}()
#8 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(140): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#9 /var/www/html/web/modules/contrib/leaflet/modules/leaflet_views/src/Plugin/views/style/LeafletMap.php(1271): Drupal\Core\Render\Renderer->renderInIsolation(Array)
#10 /var/www/html/web/modules/contrib/leaflet/modules/leaflet_views/src/Plugin/views/style/LeafletMap.php(1110): Drupal\leaflet_views\Plugin\views\style\LeafletMap->getPopupContent('node', '1562', Object(Drupal\node\Entity\Node), Object(Drupal\views\ResultRow), 'en')
#11 /var/www/html/web/modules/contrib/leaflet/modules/leaflet_views/src/Plugin/views/style/LeafletMap.php(1000): Drupal\leaflet_views\Plugin\views\style\LeafletMap->processEntityFeatures(Array, Array, Object(Drupal\views\ResultRow), Array, 'ski_point_coord...', 108, '', Array)
#12 /var/www/html/web/modules/contrib/leaflet/modules/leaflet_views/src/Plugin/views/style/LeafletMap.php(941): Drupal\leaflet_views\Plugin\views\style\LeafletMap->processGeofield('ski_point_coord...', Array, Array, Array, 'google-roadmap', '', Array)
#13 /var/www/html/web/modules/contrib/leaflet/modules/leaflet_views/src/Plugin/views/style/LeafletMap.php(898): Drupal\leaflet_views\Plugin\views\style\LeafletMap->processResultsGroups(Array, Array, Array, Array, 'google-roadmap')
#14 /var/www/html/web/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php(2213): Drupal\leaflet_views\Plugin\views\style\LeafletMap->render()
#15 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1595): Drupal\views\Plugin\views\display\DisplayPluginBase->render()
#16 /var/www/html/web/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php(2504): Drupal\views\ViewExecutable->render()
#17 /var/www/html/web/core/modules/views/src/ViewExecutable.php(1724): Drupal\views\Plugin\views\display\DisplayPluginBase->preview()
#18 /var/www/html/web/core/modules/views_ui/src/ViewUI.php(627): Drupal\views\ViewExecutable->preview('block_1', Array)
#19 /var/www/html/web/core/modules/views_ui/src/ViewPreviewForm.php(63): Drupal\views_ui\ViewUI->renderPreview('block_1', Array)
#20 /var/www/html/web/core/lib/Drupal/Core/Entity/EntityForm.php(107): Drupal\views_ui\ViewPreviewForm->form(Array, Object(Drupal\Core\Form\FormState))
#21 /var/www/html/web/core/modules/views_ui/src/ViewFormBase.php(42): Drupal\Core\Entity\EntityForm->buildForm(Array, Object(Drupal\Core\Form\FormState))
#22 [internal function]: Drupal\views_ui\ViewFormBase->buildForm(Array, Object(Drupal\Core\Form\FormState), 'block_1')
#23 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(528): call_user_func_array(Array, Array)
#24 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(370): Drupal\Core\Form\FormBuilder->retrieveForm('view_preview_fo...', Object(Drupal\Core\Form\FormState))
#25 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(625): Drupal\Core\Form\FormBuilder->rebuildForm('view_preview_fo...', Object(Drupal\Core\Form\FormState), Array)
#26 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(321): Drupal\Core\Form\FormBuilder->processForm('view_preview_fo...', Array, Object(Drupal\Core\Form\FormState))
#27 /var/www/html/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\views_ui\ViewPreviewForm), Object(Drupal\Core\Form\FormState))
#28 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#29 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#30 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(627): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#31 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(121): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#32 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#33 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(183): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#34 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#35 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#36 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#37 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#38 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(116): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#39 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(90): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#40 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#41 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#42 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(53): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#43 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#44 /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php(715): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#45 /var/www/html/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#46 {main}";}, 7, , http://test/admin/structure/views/view/ski_lift_map/preview/block_1?_wra..., http://test/admin/structure/views/view/ski_lift_map/edit/block_1, 172.21.0.4, 1771343854)
[0.002614 ms] INSERT INTO "watchdog" ("uid", "type", "message", "variables", "severity", "link", "location", "referer", "hostname", "timestamp") VALUES (1, theme, Theme hook %hook not found., a:1:{s:5:"%hook";N;}, 4, , http://test/admin/structure/views/view/ski_lift_map/preview/block_1?_wra..., http://test/admin/structure/views/view/ski_lift_map/edit/block_1, 172.21.0.4, 1771343854)
[0.001469 ms] INSERT INTO "watchdog" ("uid", "type", "message", "variables", "severity", "link", "location", "referer", "hostname", "timestamp") VALUES (1, php, %type: @message in %function (line %line of %file) @backtrace_string., a:6:{s:5:"%type";s:19:"Deprecated function";s:8:"@message";O:25:"Drupal\Core\Render\Markup":1:{s:9:"*string";s:80:"strrpos(): Passing null to parameter #1 ($haystack) of type string is deprecated";}s:9:"%function";s:40:"Drupal\Core\Theme\ThemeManager->render()";s:5:"%file";s:61:"/var/www/html/web/core/lib/Drupal/Core/Theme/ThemeManager.php";s:5:"%line";i:168;s:17:"@backtrace_string";s:7839:"#0 /var/www/html/web/core/includes/bootstrap.inc(104): _drupal_error_handler_real(8192, 'strrpos(): Pass...', '/var/www/html/w...', 168)
Steps to reproduce
Create a View with Leaflet Map style.
Set "Popup Source" to #rendered_view_fields.
Use PHP 8.3 and Drupal 11.
(Optional) Use a large number of markers to see the memory exhaustion.
Proposed resolution
Ensure that the render array passed to renderInIsolation has a proper #markup key or a valid #theme hook. Added protection against NULL values in the theme suggestions array.
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #11 | Screenshot 2026-02-23 at 10.53.34.jpg | 139.97 KB | itamair |
| #11 | Screenshot 2026-02-23 at 10.56.31.jpg | 107.41 KB | itamair |
| #7 | Debugger state showing the malformed #theme array with a NULL base hook.png | 27.7 KB | just-me |
Issue fork leaflet-3574034
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
just-me commentedComment #7
just-me commentedHello,
During the execution of the getPopupContent method, the call to $this->view->rowPlugin->render($result) may return a render array where the #theme property is malformed.
Specifically, in certain configurations, the #theme array contains a NULL value as its last element (which should normally be the base hook). See the attached screenshot for a debugger inspection.
In PHP 8.3, this causes a cascade of issues because the core ThemeManager::render() method passes this value to strrpos(). Since PHP 8.3 no longer allows passing NULL to string functions, it triggers a Deprecated function notice or a TypeError. On large datasets (e.g., thousands of markers), this leads to massive watchdog logging and immediate memory exhaustion.
Comment #8
just-me commentedComment #9
just-me commentedComment #10
itamair commentedhi @just-me thanks for reporting this ...
But I couldn't reproduce the problem that you arise.
In my testing Drupal Leaflet environments (PHP 8.3, Drupal 11, etc.) I never found/hit an invalid / malformed render array and my
$render_row['markup']['#theme'] always looks like the ones shown in the attached screenshots.
How could the $render_row result in an invalid render array, considering that $this->view->rowPlugin->render($result) would always return a string?
https://git.drupalcode.org/project/drupal/-/blob/11.x/core/modules/views...
It looks/seems generally working as designed, but would like from you a further clarification.
Could you provide more details on your detailed use case that generates what you describe?
"when using #rendered_view_fields, the code passes a malformed render array or receives a NULL theme hook, leading to a cascade of errors"
As the Steps to reproduce that you describe look indeed very generic and not generally true ... (normally it doesn't happen what you report: " the code passes a malformed render array or receives a NULL theme hook").
Comment #11
itamair commentedComment #12
itamair commentedClosing this, as no reply was added since my last request of more info.