Problem/Motivation
Under hard to tackle down circumstances an error makes admin paths like admin/structure/types/manage/node-type/fields/add-field
inaccessible with WSOD making it impossible to create new fields on any content or custom entity type from the UI:
Cannot access offset of type Drupal\Core\StringTranslation\TranslatableMarkup in isset or empty in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 45 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).
To bring up more here or where to look at or to investigate further we need hints regarding what DiscoveryTrait.php is for. Looking at api.d.org did not helped yet much. Usually you would get a listing of field types at that point entering the field creation path, so our first assumption was it belongs to query existing field types via the admin UI of that path. That's why I choose field system at first but maybe we need to move it to language system.
Reusing an existing field works without issues from UI and this is probably why we discovered the issue too late to have an idea what change here lately has caused the error. But the irreversible behavior and WSOD made me consider a core issue report. Because we maybe do have an underlying problem here where contrib modules do something or probably rather left or removed something they should not be allowed to after removal of settings or uninstalls which causes breaking core here. Maybe we need another step/check for safety to prevent this.
Steps to reproduce
Sadly this will be hard to reproduce and is probably caused by left overs from module configurations, installs and uninstalls and many back and forth in a longer site building process. Discovered here on a Drupal 11.04 upgraded project which came from 10.3.3 with 2 languages set up and activated for content, interface and configuration and with far too much contrib modules. All uninstalled step by step in the hope to maybe find the one causing it. First we thought modules creating new field types are the most suspicious, but non of them uninstalling made a change. Which makes sense if this is caused by something rather "missing" than being still around.
Line mentioned in the error log is 45 in core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php (git.drupalcode.org link):
if (isset($definitions[$plugin_id])) {
The whole block:
protected function doGetDefinition(array $definitions, $plugin_id, $exception_on_invalid) {
// Avoid using a ternary that would create a copy of the array.
if (isset($definitions[$plugin_id])) {
return $definitions[$plugin_id];
}
elseif (!$exception_on_invalid) {
return NULL;
}
Furthermore this error appears on UI only. The field creation process via console (drush field:create
) works without flaws.
Proposed resolution
There are some issues open mentioning TranslatableMarkup
and other Cannot access offset of type xxx
issues all not related in that sense but interestingly enough most of the latter raised in the last 2 years. So it probably belongs to newer PHP versions being more strict in the requirements of type checking and error behavior. Mainly in cases where array are empty or similar. Some of the issues discuss is_array() and similar workarounds.
Maybe related but I did not wanted to reference them yet if not, to prevent unnecessary noise:
- #3366788: TranslatableMarkup passed to t() function when config property has no label set.
- #3365498: Add Missing Symfony Validators to Drupal Constraint Validator
- #2719553: Log error when a TranslatableMarkup is created with a non-string input
- #2571677: Ensure no empty strings are fed to TranslatableMarkup
Remaining tasks
Needs more steps/tests to reproduce.
Full error log
The website encountered an unexpected error. Try again later.
TypeError: Cannot access offset of type Drupal\Core\StringTranslation\TranslatableMarkup in isset or empty in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 45 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).
Drupal\Core\Plugin\DefaultPluginManager->getDefinition() (Line: 16)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance() (Line: 76)
Drupal\Component\Plugin\PluginManagerBase->createInstance() (Line: 136)
Drupal\field_ui\Form\FieldStorageAddForm->processFieldDefinitions() (Line: 80)
Drupal\field_ui\Form\FieldStorageAddForm->buildForm()
call_user_func_array() (Line: 528)
Drupal\Core\Form\FormBuilder->retrieveForm() (Line: 279)
Drupal\Core\Form\FormBuilder->buildForm() (Line: 73)
Drupal\Core\Controller\FormController->getContentResult()
call_user_func_array() (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 593)
Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 183)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 53)
Asm89\Stack\Cors->handle() (Line: 50)
Drupal\ban\BanMiddleware->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 709)
Drupal\Core\DrupalKernel->handle() (Line: 19)