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:

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)

Issue fork drupal-3475505

Command icon 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

dqd created an issue. See original summary.

dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
dqd’s picture

Issue summary: View changes
quietone’s picture

Version: 11.0.x-dev » 11.x-dev
dqd’s picture

Status: Active » Postponed

Thanks @quietone for correcting the version scope.

To save time of all who want to chime in I would like to let you know: I probably am about to change the summary over the next days after more investigations again. Because we're may be on the trail of something in a bigger picture here which maybe rather leads to an FR, like:

"Let's provide a exception not breaking front page or admin pages for all the type/offset errors raising with newer PHP versions."

dqd’s picture

Maybe another related: #3467538: Cannot access offset of type Drupal\Core\StringTranslation\TranslatableMarkup in isset or empty in Drupal\update\ProjectCoreCompatibility->getPossibleCoreUpdateVersions

(still not linking them as issue ref since it still needs to finally cleared IF and HOW they are related)

As I already stated in the issue summary and since PHP used to be a very "forgiving" language we probably have a mass of such hidden issues in core. See this old SO thread with comments on newer PHP versions below: https://stackoverflow.com/questions/1873970/cannot-use-string-offset-as-...

cassien’s picture

hi there,
I'm facing this issue with d11.
Everything was working pretty good, and this morning... field additions broke on content type, product types, commerce types, etc.
I tried to trace the problem by adding a line of code in the DiscoveryTrait file :
if (isset($plugin_id)) { print($plugin_id); echo "<br>"; }
It results in a long list, in which the last value is "Commerce" (with cap).
I lowercased $plugin_id, and it finally throws another error :
TypeError: Cannot access offset of type Drupal\Core\StringTranslation\TranslatableMarkup on array in Drupal\field_ui\Form\FieldStorageAddForm->processFieldDefinitions() (line 141 of core/modules/field_ui/src/Form/FieldStorageAddForm.php).
The last values displayed in my list are now "commerce" then "general".
Hope it helps ... it's my sixth hour of research :D I need a break and a pizza !

cassien’s picture

Ok guys,
I have the confirmation that the issue is related to commerce in my case.
The freak variables are isolated with this code :

    if($plugin_id=="Commerce") {
      echo "<pre>";
      print_r($definitions);
      echo "</pre><br>";
    } else {
          // 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;
          }
    }

The add field form is working now, even if the problem is not solved.
At the moment I don't understand what's happening.

qiutuo’s picture

I'm also getting the same error today, and the research found that it was caused by the missing "category" in the custom field.

dqd’s picture

Status: Postponed » Needs work

Thanks for all the reports. This indicates that we maybe need a proper exception handling and warning for such cases to prevent WSOD and sites being unmaintainable in this state.

jackwrfuller’s picture

I have encountered this issue as well, but in my case it was with the Prism module: #3491768: Prism causes WSOD on field creation for all field types

In my case, I think the problem was caused by setting 'category' to a Translation in the FieldType definition.

EDIT: I think its because of this change to the API: https://www.drupal.org/node/3375748

berdir made their first commit to this issue’s fork.

berdir’s picture

Status: Needs work » Needs review

Created a merge request that throws an exception when the field type category is not valid.

anybody’s picture

We're running into a very similar issue in the function:

TypeError: Cannot access offset of type Drupal\Core\StringTranslation\TranslatableMarkup on array 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: 116)
Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 90)
Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 50)
Drupal\ban\BanMiddleware->handle() (Line: 96)
Drupal\crowdsec\Middleware->handle() (Line: 263)
Drupal\shield\ShieldMiddleware->bypass() (Line: 162)
Drupal\shield\ShieldMiddleware->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 49)
Drupal\remove_http_headers\StackMiddleware\RemoveHttpHeadersMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 709)
Drupal\Core\DrupalKernel->handle() (Line: 19)

I'll try to find the root cause now.

anybody’s picture

Status: Needs review » Reviewed & tested by the community

Update: The attached MR adding an exception with very helpful details GREAT!

Instead of the message in #20 we now see a nice verbose error:
Exception: Invalid field category for field typeentity_reference_display, category must be the ID of aa defined field category, got Referenz. in Drupal\field_ui\Form\FieldStorageAddForm->processFieldDefinitions() (line 136 of core/modules/field_ui/src/Form/FieldStorageAddForm.php). from which we found out it's a contrib issue:
#3486365: Using a translatable string as a category for field type is deprecated (breaks D11)

RTBC! Would be nice to cherry-pick this into 10.4.x and 10.5.x

grevil’s picture

Confirming RTBC and fixed typo

anybody’s picture

godotislate’s picture

Status: Reviewed & tested by the community » Needs work

There's still a missing space typo.

anybody’s picture

Status: Needs work » Reviewed & tested by the community

Thanks @godotislate, sorry I didn't see that. Fixed that. As both were only textual changes, I'm setting this back to RTBC, but feel free to confirm that.

quietone’s picture

I read the IS, MR and the comments . I didn't find any unanswered questions. I did leave a comment on the MR but before taking action it would be better to get the opinion of another committer to determine if this is the correct fix.

catch’s picture

Status: Reviewed & tested by the community » Needs work

I think I agree with @quietone's review - doesn't look like it loses any information from the error message, and moving one line earlier seems fine too.

godotislate’s picture

Status: Needs work » Needs review

Made the change per @quietone and @catch. Back to NR.

Does this need a test? It was at RTBC previously without one.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

As a bug I would assume it would need a test as mentioned no?

berdir’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -Needs tests

We have some rules around skipping tests if the fix is straightforward and unlikely to break again. This is just a safety guard against code that was not properly updated to D10+ to provide a more helpful error.

Testing it would require that we add an invalid test implementation of a field type and that seems a lot of trouble for this.

Lets try :)

maxilein’s picture

Thanks. It is easy to find the culprit now!

berdir’s picture

Status: Reviewed & tested by the community » Needs work

#3386762: Use modals in field creation and field edit flow completely removed the exception. In manual testing, I don't even get far enough because there's an assertion in \Drupal\Core\Field\FieldTypePluginManager::getGroupedDefinitions(), but that was there before and it's not as helpful I think. Maybe instead of that assert(), we should throw the exception there?

redeight’s picture

Ran into this issue today. Saw someone mention that it might be triggered by this api change https://www.drupal.org/node/3375748. Sure enough, grep "category = @Translation(" -r . | grep "FieldType" got a hit in our modules directory. Adjusting the offending module fixed the issue.

cb’s picture

Confirming what @redeight posted in #33 - removing an incorrect category on a @FieldType annotation fixed this problem for me also. Couldn't have found the issue though without the patch.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.