Problem/Motivation

/admin/content view is not working - fatal error.

Dblog reports 3 different errors:
Error: Call to a member function getCacheTags() on null in Drupal\views\Plugin\views\query\Sql->getCacheTags() (Line 1677 in /app/web/core/modules/views/src/Plugin/views/query/Sql.php)

Error: Call to a member function getCacheMaxAge() on null in Drupal\views\Plugin\views\query\Sql->getCacheMaxAge() (Line 1694 in /app/web/core/modules/views/src/Plugin/views/query/Sql.php)

Error: Call to a member function getCacheTags() on null in Drupal\views\Plugin\views\cache\CachePluginBase->getRowCacheTags() (Zeile 320 in /app/web/core/modules/views/src/Plugin/views/cache/CachePluginBase.php)

The issue lies in web/core/modules/views/src/Plugin/views/query/Sql.php in getAllEntities(line 1707) method, where $row->_relationship_entities can be NULL but are not checked if emtyp (as $row->_entity is).

Steps to reproduce

It is related to our content so I'm not sure how exactly to reproduce. On some of our migrated nodes an entity reference field is missing.

Proposed resolution

I would actually put a check into the 3 methods that are throwing php errors to check if the entity is not empty and then perform caching operations (merging tags or getRowCacheTags).

CommentFileSizeAuthor
#2 get_cache_tags_null-3169694-2.patch1.56 KBuseernamee

Issue fork drupal-3169694

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

useernamee created an issue. See original summary.

useernamee’s picture

StatusFileSize
new1.56 KB

I'm attaching proposed patch.

useernamee’s picture

Assigned: useernamee » Unassigned
Status: Active » Needs review
fago’s picture

Title: getCacheTags() on null » Fatal error getCacheTags() on null on admin/content Views page
fago’s picture

Title: Fatal error getCacheTags() on null on admin/content Views page » Fatal error "getCacheTags() on null" on admin/content Views page
useernamee’s picture

Issue summary: View changes
gatorjoe’s picture

I deleted the group relationship for a piece of content and started receiving an error. Patch #2 resolved my issue. For reference here is the corresponding log message:

Error: Call to a member function getCacheTags() on null in Drupal\views\Plugin\views\query\Sql->getCacheTags() (line 1677 of /app/web/core/modules/views/src/Plugin/views/query/Sql.php)
#0 /app/web/core/modules/views/src/Plugin/views/cache/CachePluginBase.php(250): Drupal\views\Plugin\views\query\Sql->getCacheTags()
#1 /app/web/core/modules/views/src/Plugin/views/cache/CachePluginBase.php(117): Drupal\views\Plugin\views\cache\CachePluginBase->getCacheTags()
#2 /app/web/core/modules/views/src/ViewExecutable.php(1431): Drupal\views\Plugin\views\cache\CachePluginBase->cacheSet('results')
#3 /app/web/core/modules/views/src/ViewExecutable.php(1454): Drupal\views\ViewExecutable->execute(NULL)
#4 /app/web/core/modules/views/src/Plugin/views/display/Page.php(183): Drupal\views\ViewExecutable->render()
#5 /app/web/core/modules/views/src/ViewExecutable.php(1630): Drupal\views\Plugin\views\display\Page->execute()
#6 /app/web/core/modules/views/src/Element/View.php(77): Drupal\views\ViewExecutable->executeDisplay('page_1', Array)
#7 [internal function]: Drupal\views\Element\View::preRenderViewElement(Array)
#8 /app/web/core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php(100): call_user_func_array(Array, Array)
#9 /app/web/core/lib/Drupal/Core/Render/Renderer.php(781): Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_ren...', 'silenced_deprec...', 'Drupal\\Core\\Ren...')
#10 /app/web/core/lib/Drupal/Core/Render/Renderer.php(372): Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array)
#11 /app/web/core/lib/Drupal/Core/Render/Renderer.php(200): Drupal\Core\Render\Renderer->doRender(Array, false)
#12 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(226): Drupal\Core\Render\Renderer->render(Array, false)
#13 /app/web/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}()
#14 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(227): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#15 /app/web/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(117): Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\CurrentRouteMatch))
#16 /app/web/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))
#17 [internal function]: Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#18 /app/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent), 'kernel.view', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#19 /app/vendor/symfony/http-kernel/HttpKernel.php(156): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object(Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent))
#20 /app/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#21 /app/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /app/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /app/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 /app/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /app/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /app/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /app/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#31 {main}

Side note, incredibly happy to encounter an error and find a solution that was posted only hours before! :) Thank you!!!

lendude’s picture

Status: Needs review » Postponed (maintainer needs more info)
Issue tags: -cache, -views +Needs steps to reproduce

Usually this type of change just hides the underlying problem. Nice to get things working again on a broken system but not something we want to do al the time.

Without steps to reproduce on a clean install, it becomes hard to see if this is a situation that you can get into without having broken content.

mikelutz’s picture

For what it's worth, I came across this error and it was due to having the multiversion module installed. Multiversion adds a soft delete to nodes, where they stay in the node table, but adds a _deleted flag to the table. Views gets it's list of entity ids through raw sql queries that don't filter out these deleted nodes, but when it goes to load them, it loads them through multiversion's overridden entity storage that won't load the deleted entities. So you end up with views thinking it has entities to loop through, but they are NULL because of multiversion.

In this case, you can add a filter to your view that filters out rows with the deleted flag, this will fix your views, because views will filter those entities out at the sql level, and then there won't be any entity ids to load that don't actually exist.

useernamee’s picture

@mikelutz thanks for the explanation! It makes sense. Are you suggesting that this is actually something multiversion should fix (or warn about at least)?

lendude’s picture

Version: 8.8.x-dev » 9.1.x-dev
Status: Postponed (maintainer needs more info) » Closed (works as designed)
Issue tags: +Bug Smash Initiative

Moving this to the Drupal core version currently receiving bug fixes.

I get this error a lot too, but it is always due to the problem pointed out in #7 were I messed up my group relationships (probably by manually deleting stuff from my local DB, or half reverting part of a migration)

I'm going to tentatively mark this 'works as designed' because it seems to be related to having corrupt data in your database or being caused by contrib. Feel free to reopen this if you have some steps to reproduce this on a vanilla install or if you feel like this is a situation we should handle in core.

zcht’s picture

Unfortunately I have the same problem, but this patch does not help. I noticed it when I enable the metatag views submodule and am on a search view. I have listed the issue here: https://www.drupal.org/project/metatag/issues/3245876

See also observations listed in my second comment, is this possibly the problem?

Deprecated: assert(): Calling assert() with a string argument is deprecated in /var/www/html/docroot/core/lib/Drupal/Core/Cache/Context/ContextCacheKeys.php on line 26

Deprecated: assert(): Calling assert() with a string argument is deprecated in /var/www/html/docroot/core/lib/Drupal/Core/Cache/CacheableMetadata.php on line 127
Attached is the error output.

Deprecated function: assert(): Calling assert() with a string argument is deprecated in Drupal\Core\Cache\CacheableMetadata->merge()

What would I need to adjust to fix this issue for my search view? Many thanks.

zcht’s picture

Version: 9.1.x-dev » 9.2.x-dev
Status: Closed (works as designed) » Active
lendude’s picture

Status: Active » Closed (works as designed)

@zcht the assert messages should be unrelated to this. As pointed out in #11, this error is usually due to missing/malformed/corrupt data in your database or a contrib module doing something that it probably shouldn't be doing.

Feel free to reopen this if there is some way to reproduce this with a clean Drupal core install, I'm still unsure if this is something we can or should guard against in core.

studgate’s picture

this also works for Drupal 9.4.5

maskedjellybean’s picture

I ran into this error as well, but decided to figure out what the root cause was instead of applying the patch. I can confirm that this is caused by corrupted data as @Lendude said.

In my case there were nodes that failed to load. getCacheTags() is then called on null instead of the node entity resulting in the error. You could argue that core should check for this, but I think there is an assumption that a node should never fail to load, and that if it does you probably want to know about it so that you can fix it.

What I found is that there were nodes that existed in the node_field_data table that did not exist in node. This should never happen.

Here's the query I ran to determine that:

SELECT nid FROM node_field_data
WHERE nid NOT IN (SELECT n.nid from node n)

That gave me a list of 7 corrupted nodes. I then wrote a hook_update_N() that loops through the nodes, recreates them and deletes them. Here's what MY update hook looked like, but DO NOT RUN THIS AS IS. You need to customize it for your situation. Yours may be more or less complicated than mine. You need to change "NID_HERE" to the nids and content types of YOUR corrupted nodes. ALWAYS test update hooks locally multiple times before running on production.

/**
 * Delete corrupted nodes that cause error 'getCacheTags() on null'.
 *
 * See:
 * https://www.drupal.org/project/drupal/issues/3169694
 *
 * These nodes exist in node_field_data table
 * but not in node table. They are unable to be loaded.
 * To fix we'll recreate and delete them properly.
 */
function my_module_update_8001(&$sandbox) {
  $nids_to_delete = [
    NID_HERE => 'basic_page',
    NID_HERE => 'basic_page',
    NID_HERE => 'basic_page',
    NID_HERE => 'event',
    NID_HERE => 'basic_page',
    NID_HERE => 'basic_page',
    NID_HERE => 'event',
  ];

  foreach ($nids_to_delete as $nid => $type) {
    // Double check that the node cannot be loaded.
    // If it can be loaded then there is no reason to
    // delete it.
    $node = Node::load($nid);
    if ($node) {
      continue;
    }

    // Delete node from field tables that prevent
    // it from being recreated due to
    // duplicate id entry. We only want to delete
    // what is necessary for the node to be recreated.
    $database = \Drupal::database();
    $tables = [
      'node__field_publish_archive_scheduling',
    ];
    foreach ($tables as $table) {
      $database->query("DELETE from {$table} WHERE entity_id LIKE $nid");
    }

    // Events have more field tables that cause trouble.
    if ($type === 'event') {
      $tables = [
        'node__field_add_to_calendar',
        'node__field_enable_registration',
        'node__field_event_show_online_location',
        'node__field_registration_message',
      ];
      foreach ($tables as $table) {
        $database->query("DELETE from {$table} WHERE entity_id LIKE $nid");
      }
    }

    // Recreate node so it can be deleted
    // properly. Hopefully any references
    // to it are deleted from other tables, which
    // is what should have happened in the first place.
    $node = Node::create([
      'type' => $type,
    ]);
    $node->set('nid', $nid);
    $node->set('title', "$nid to be deleted");
    $node->save();
    $node->delete();
  }
}
chancenyasulu’s picture

Can we change this parts

if (empty($entity)) {
+ continue;
+ }

by using !is_null and instead of continue; replace it with these lines

first part: $tags = Cache::mergeTags($tags, $entity->getCacheTags());
second part: $tags = Cache::mergeTags($entity->getCacheTags(), $tags);
third part: $max_age = Cache::mergeMaxAges($max_age, $entity->getCacheMaxAge());

if(!is_null($entity)){
$tags = Cache::mergeTags($entity->getCacheTags(), $tags);
}

pganore1@gmail.com’s picture

Any idea, when will this be merged into Drupal 10 ?

timefor’s picture

I encountered this exact error. Turned out it was due to a corrupted row in the 'users' table of the database. The issue arose when I transferred data between environments: MySQL failed to create the anonymous user with UID=0, instead assigning the next available UID. This newly assigned UID had no corresponding entry in the 'users_data' table, causing disruptions in views loading content associated with the anonymous user.

Though the above patch helped identify the root cause, it wasn't a permanent fix. To resolve the problem, I manually set the UID for the anonymous user to 0 in the database, eliminating the need for the patch.

I used Navicat MySQL for data transfer, but I'm uncertain if that's where the UID discrepancy began, or if it might be related to some default setting within the SQL database that prevents assignment of a UID of 0.

I attempted to run the process in #16, but I had no corrupt nodes so it wasn't the problem. Anyway, just something else to try for the next person tracking down this views error.

robcarr’s picture

@TimeFor - thanks for solution. I'd seen the error and it was exactly that issue where I'd transferred databases between environments. Worth noting as a potential Drupal general problem.

It was a case of looking in users_field_data table and comparing UIDs to the users table and seeing where there was a mismatch. In my case it was the highest UID in the users table that was erroneous - just edited the users table in PMA and altered the relevant UID value to 0

sadikyalcin’s picture

@TimeFor what a life saver. That was exactly the issue for me. I moved to a new db and watchdog kept breaking with cache errors.

Error: Call to a member function getCacheTags()
Error: Call to a member function getCacheMaxAge()

aniketd’s picture

#2 patched code works for the Drupal 11.1.1

cilefen’s picture

Status: Closed (works as designed) » Postponed (maintainer needs more info)
quietone’s picture

Version: 9.2.x-dev » 11.x-dev

Drupal 9 is End of Life.

Changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to the Core change policies.

alphex’s picture

Patch in comment #2 worked on 10.4.6

anaconda777’s picture

I got the same error on Drupal 10.4.7
It happened after deleting some nodes meanwhile ECA was analyzing the nodes and setting their moderation states etc. Maybe this was not the reason.

Anyway like before someone instructed I managed to fix it and deleted the corrupted node like this:

1. Go to mysql console
2. use databasename;
3. SELECT nid FROM node_field_data WHERE nid NOT IN (SELECT n.nid from node n);
4. 	DELETE FROM node_revision WHERE nid = 12553;
4.1	DELETE FROM node_field_revision WHERE nid = 12553;
4.2   DELETE FROM node_field_data WHERE nid = 12553;
4.3   DELETE FROM node WHERE nid = 12553;
afeijo’s picture

I got this error for months specially at the Reports page, and sometimes at the Content page.

Scary to se a 2020 patch still not commited to drupal

#2 patch works, thanks! I'm using version 10.4.6 too btw

brunoalmeida’s picture

Patch #2 worked on 10.5.1

mikelutz’s picture

Scary to se a 2020 patch still not commited to drupal/blockquote>

It's not committed because it doesn't fix any bug with Drupal. It only hides an error due to a corrupted database. There are plenty of instructions in this thread on how to fix the underlying problem with your site.

bdunphy’s picture

It only hides an error due to a corrupted database.

#2 also prevents a WSOD. Checking that a variable contains / does not contain a value is good programming practice. One could take the patch and add in a logger message. Something to warn the site maintainer that they need to check the data integrity.

millenniumtree’s picture

@mikelutz
Please listen to the consensus here. This type of thinking (bad data, no issue!) is why Drupal objects feel so fragile. If a simple if() can prevent a site bombing, then please implement it! The error being produced doesn't tell you which object is at fault, or how to correct it, it's just a WSOD. It's absolutely unacceptable that this issue gets reported, acknowledged, and patched by the community, but IGNORED by the Drupal team, for coming up on FIVE YEARS.

anaconda777’s picture

I got this error again, it was because a bad ECA model, which deleted a node

lazzyvn’s picture

I got this error when i go to /admin/reports/dblog
apply this patch it works

frob’s picture

Title: Fatal error "getCacheTags() on null" on admin/content Views page » Fatal error "getCacheTags() on null" on admin/content Views displays when views references entities that don't exist
Status: Postponed (maintainer needs more info) » Needs review

While it would be nice for this to be fixed by fixing the content, it doesn't change the fact that this needs to be fixed on output as well.

A "better" fix would be for the error to happen when the content is corrupted. This isn't something that is happening when users are editing the DB directly. It is happening when entities are being deleted. I wish I had concrete example of how this is happening. The closest I have gotten is when a WSOD gets logged dealing with user data for an Anonymous user. That breaks dblog page. But I don't see that as the error here.

The bug this fixes is that views is trying to calculate cache on entities that don't exist.

frob’s picture

Status: Needs review » Reviewed & tested by the community

Applying this patch fixes the issue of views breaking when the calculated referenced entities don't exist. I might make a new issue to deal with the Anonymous user bugs if I can get time to replicated it.

adrianm6254’s picture

I applied patch #2 and it fixed my 'Recent log messages' going WSOD

catch’s picture

Status: Reviewed & tested by the community » Needs work

This needs to be an MR so that tests run etc., it could also probably use explicit test coverage.

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

mayurgajar’s picture

Assigned: Unassigned » mayurgajar

frob’s picture

Does this need work? Looks like the MR test failed on lint.

mayurgajar’s picture

Assigned: mayurgajar » Unassigned
Status: Needs work » Needs review

Added MR: https://git.drupalcode.org/project/drupal/-/merge_requests/13934
Steps to reproduced:
1. Migrate content from site
2. the issue occurs to the migrated content
3. check the nodes / user data
4. user encounter issue: Error: Call to a member function getCacheTags() on null

Apply the MR and check again
MR raised against 11.x

smustgrave’s picture

Status: Needs review » Needs work

#37 still applies

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.

jonathan_hunt’s picture

fwiw, patch in #2 still applies to 10.6.5. However, I think rather than silently ignoring data errors such as dangling references they should be logged so they can come to the attention of an administrator.

Given that Drupal core has an issue acknowledging that dangling references are not cleaned up https://www.drupal.org/project/drupal/issues/2723323 I think it's important for UX not to WSOD when such a reference is encountered.

jonathan_hunt’s picture

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

sivaji_ganesh_jojodae changed the visibility of the branch 3169694-fatal-error-getcachetags to hidden.

sivaji_ganesh_jojodae changed the visibility of the branch 3169694-fatal-error-getcachetags to active.

sivaji_ganesh_jojodae’s picture

Status: Needs work » Needs review

I've updated the previous merge request after rebasing. The pipeline now appears to be successful.

smustgrave’s picture

Status: Needs review » Needs work

Most issues need more then rebasing. Since steps still have not been provided moving back.