Error UnexpectedValueException: Object not found in SplObjectStorage->offsetGet()

Created on 29 May 2024, 7 months ago

Problem/Motivation

When we have more than one item in fiield, on render we have fatal error

UnexpectedValueException: Object not found in SplObjectStorage->offsetGet() (line 102 of modules/contrib/bricks/src/Bricks.php)

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

🇺🇦Ukraine AndrewsizZ

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

Merge Requests

Comments & Activities

  • Issue created by @AndrewsizZ
  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    Tell us more. I mean, Smartsheet is running this code without a problem and we have multiple value fields aplenty.

  • Hi,

    I'm reproducing this after a D9 > D10 upgrade, updating Bricks from 2.0.1 to 2.1.2, but only on one page so far.
    After quickly fixing this error to see if the page would load, I noticed another issue that should normally be fixed in this version of the module: only the "latest" reuse of a layout have its children visible (reported here: https://www.drupal.org/project/bricks/issues/3301816 🐛 Repeated layouts are missing their children Fixed ).

    Let me know what information you'd need to investigate on this.

  • I found this issue that is related, the patch seems to have similarities with your major depth fixing patch.
    You might want to close it.

    https://www.drupal.org/project/bricks/issues/3295645

  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    Well, Katherine is the Staff Engineer on the team where I am Senior Engineer so any similarities are to be expected. Any chance I could get a database dump to see what goes wrong?

  • Hi,
    Thanks for your proposal but it's a customer site and sharing a database is not an option.
    I tracked it down to the fieldItem() function.
    In newElements() I dumped $parent_items before the foreach() loop and got this:

    SplObjectStorage {#6765 ▼
      storage: array:4 [▼
        0 => {▼
          object: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3433 ▶}
          info: class@anonymous {#6770}
        }
        1 => {▼
          object: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3435 ▶}
          info: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3433 ▶}
        }
        2 => {▼
          object: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3437 ▶}
          info: class@anonymous {#6770}
        }
        3 => {▼
          object: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3439 ▶}
          info: Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3437 ▶}
        }
      ]
    }

    Where objects are #3433, #3435, #3437, #3439 and where #3433 and #3437 are two instances of the same layout.

    Then in the foreach() loop I dumped the return of static::fieldItem($content) and got this:

    Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3437 ▶}
    Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3435 ▶}
    Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3437 ▶}
    Drupal\bricks\Plugin\Field\FieldType\BricksTreeItem {#3439 ▶}

    Where the first layout instance #3433 is replaced with the second one #3437.

    I don't know all the intricacies of the module and the need behind the fieldItem() function, but we already have the BricksTreeItems in the $items variables, so I simply fixed both bugs (object not found + 3301816) by replacing "$field_item = static::fieldItem($content)" with "$field_item = $items[$key]".

    I join a patch that is working in my case.

  • Sorry, I just noticed that I didn't make it clear in #4 what I was reproducing.
    It's just the error in the title of the issue, not the IS.

  • Issue was unassigned.
  • Status changed to Needs review 5 months ago
  • Status changed to Needs work 5 months ago
  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    I do not understand. There's a comment explaining why your patch doesn't work, it links the issue related. Your are removing a very important fix. It was one of the hardest problems I worked on related to bricks. This patch can not be committed as it stands. Yes it works for you but only because you do not have an access handler messing with paragraphs.

    Could you please check whether

          $field_item = static::fieldItem($content);
          if ($field_item && $parent_items->contains($field_item)) {
            $parent_item = $parent_items[$field_item];
            // Only keep elements whose parent is in the new tree. If it is not then
            // the parent was access denied.
            if ($parent_keys->contains($parent_item)) {
              $new_elements[$key] = static::newElement($content, $field_item, $parent_keys[$parent_item]);
              $parent_keys[$field_item] = $key;
              $key++;
            }
          }
    

    works?

  • Hi, thanks for your reply.
    Sorry, maybe the "needs review" status was misleading.
    My post and patch were not supposed to be a solution, it's the start of an investigation and a POC to help you as I can't send you a database dump.
    As I said (and you confirmed) I'm not the one who should work on this because I don't know the intricacies (and I don't have time to learn them).
    I just want to help move things forward.

    About your changes proposal, I don't need to test it because as I explained in #7 the problem lies in the fieldItem() function, which you don't touch in this piece of code. It's just a better version of AndrewsizZ's patch.
    Sure, it would not throw an "Object not found" error anymore, but just by concealing the issue, not actually fixing it. With this fix I would still have missing items on my page.
    Have you seen what I get when I dump the return of fieldItem() ? One instance of the same layout is replaced with another instance, it's completely abnormal and why I get an "Object not found" error.
    This function must get fixed.

    Let me know if there's anything else I can test to help you.

  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    OK. Sorry, I didn't fully understand it yesterday although it is a good report -- once again, sorry about that. May I ask what entity type and which formatter is being used here for layout?

  • The layout entites are Drupal\eck\Entity\EckEntity. Not sure about the formatter, sorry ("container_layout" is selected in the options, is that it?).

    I noticed something that might be of interest.
    There are actually two bricks fields on this content type. I just tested (module unpatched) creating a new node with multiple instances of the same layout in only one field and the items in the first instance of the layout were missing as "expected", but no error was thrown. I then added an instance of the same layout in the other field and then the error was thrown.
    I checked and indeed the already existing node uses the same layout in both fields.

  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    Thanks for your work on this. Please upload the database dump of the reproduction site you created. Thanks.

  • Hi,
    Sorry I can't do that, as mentioned in #7. My employer forbids it.
    I'll try to find time for testing it on a vanilla Drupal installation and confirm whether or not it's related to my project specifically.

  • Status changed to Postponed: needs info 5 months ago
  • Needs steps to reproduce.

  • Status changed to Active 2 months ago
  • Here's the backtrace:

    #0 /var/www/html/web/modules/contrib/bricks/src/Bricks.php(33): Drupal\bricks\Bricks::newElements()
    #1 /var/www/html/web/modules/contrib/bricks/bricks.module(18): Drupal\bricks\Bricks::nestItems()
    #2 [internal function]: bricks_preprocess_field()
    #3 /var/www/html/web/core/lib/Drupal/Core/Theme/ThemeManager.php(261): call_user_func_array()
    #4 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(491): Drupal\Core\Theme\ThemeManager->render()
    #5 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(504): Drupal\Core\Render\Renderer->doRender()
    #6 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(248): Drupal\Core\Render\Renderer->doRender()
    #7 /var/www/html/web/core/lib/Drupal/Core/Template/TwigExtension.php(476): Drupal\Core\Render\Renderer->render()
    #8 /var/www/html/vendor/twig/twig/src/Environment.php(391) : eval()'d code(141): Drupal\Core\Template\TwigExtension->escapeFilter()
    #9 /var/www/html/vendor/twig/twig/src/Template.php(393): __TwigTemplate_7657e38b4f6b3ec0ecd5db3f277a5355->doDisplay()
    #10 /var/www/html/vendor/twig/twig/src/Template.php(349): Twig\Template->yield()
    #11 /var/www/html/vendor/twig/twig/src/Template.php(364): Twig\Template->display()
    #12 /var/www/html/vendor/twig/twig/src/TemplateWrapper.php(35): Twig\Template->render()
    #13 /var/www/html/web/core/themes/engines/twig/twig.engine(33): Twig\TemplateWrapper->render()
    #14 /var/www/html/web/core/lib/Drupal/Core/Theme/ThemeManager.php(348): twig_render_template()
    #15 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(491): Drupal\Core\Theme\ThemeManager->render()
    #16 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(248): Drupal\Core\Render\Renderer->doRender()
    #17 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(238): Drupal\Core\Render\Renderer->render()
    #18 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(638): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
    #19 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(231): Drupal\Core\Render\Renderer->executeInRenderContext()
    #20 /var/www/html/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(128): Drupal\Core\Render\MainContent\HtmlRenderer->prepare()
    #21 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/MainContentViewSubscriber.php(90): Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse()
    #22 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
    #23 /var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func()
    #24 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(186): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
    #25 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
    #26 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle()
    #27 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
    #28 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
    #29 /var/www/html/web/core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle()
    #30 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\big_pipe\StackMiddleware\ContentLength->handle()
    #31 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass()
    #32 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
    #33 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
    #34 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
    #35 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle()
    #36 /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php(741): Drupal\Core\StackMiddleware\StackedHttpKernel->handle()
    #37 /var/www/html/web/index.php(19): Drupal\Core\DrupalKernel->handle()
    #38 {main}
  • This matches the definition of major bugs :

    Trigger a PHP error through the user interface, but only under rare circumstances or affecting only a small percentage of all users, even if there is a workaround.

  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    Thanks for the excellent reproduction instructions. They really are great.

    $entity->_referringItem can't be two things when $entity is the same object. $node is kept around in a static place (MemoryCache) and so when it's rendered twice the _referringItem will get overridden. This causes the problem when bricks preprocesses the rendered first field item $entity->_referringItem points to the second field item and things go wrong in a hurry.

    This gets real interesting real quick because we have no way then to find the rendered field item from the render array?

    I will ask around.

  • 🇨🇦Canada Charlie ChX Negyesi 🍁Canada

    I made a rather general fix, it's always the same problem we have been struggling with for years now. Hopefully this one is a more workable one.

  • Great news!
    Thanks for fixing this.

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

Production build 0.71.5 2024