How to Kill your Drupal Site: Database Cache

Juggling Git branches between a Production, Staging, Development and Localhost environment can make for exciting errors every now and then. Drupal often labels these errors as 'unexpected'--an obvious but often unhelfpul label. The culprit is often the database cache--here's a real life walk through of how it might be fixed.

Quick note here: I'm working with Drupal 8--although, the process documented here is more or less the same for Drupal 7 or even Drupal 9...

I recently ran some Drupal module updates on our Development site; one of those updates required a database update--namely, the Google Tag Manager module. I brought down the branch with module updates onto my localhost and then imported a copy of my Production database to continue the work on my computer. Upon loading the site, I encountered an unexpected error:

unexpected error message
Oops

Bummer!--but not the end of the world. This happens to me more often than I'd like to admit; it's almost definitely a cache issue: the module updates required a database update, and my Production DB doesn't yet have them.

Now, I don't run Drush on my localhost, so I can't get to the cache on the command line. This leaves one solution: get into the database and clear the cache manually. That's not a big deal, but just to be on the safe side, let's get into the settings.php and turn on verbose error logging. This will give me just a wee bit more diagnostic info so I can be sure the issue is actually the cache.

If you haven't ever turned on verbose error logging, here's how you do it (for Drupal 8; don't recall if this syntax is the same for D7). You'll want to open your settings.php file, head to the last line and enter the following:

$config['system.logging']['error_level'] = 'verbose';

I usally keep this commented out at the end of my settings.php so that I don't have to go search for it every time I need it. Just remove the comment bars ( // ) and you're good to go.

// $config['system.logging']['error_level'] = 'verbose';

After turning on verbose error reporting, this is what I find:

verbose error report
If you're like me, your first instinct will be to murmur a mild, "WTF!?" and go cry in the corner. The more times I do this, though, the more I appreciate the output; as daunting as it seems, it's light-years better than the alternative: a completely blank screen.

Okay... the google_tag_container entity type doesn't exist. A lot of this output can probably be ignored. The bulk of it really only looks like a list of which files and which lines are calling for the entity type. The important take away from the error is that it obviously has something to do with my Google Tag Manager module update. 

Now, the best thing to do at this point would be to go and manually clear all the cache tables from the database. That's not a particularly daunting task: login to PHPMyAdmin, backup your database first (see "export" tab), then find any table with the word 'cache' in it and drop it:

cache tables in php my admin
If you're hosting multiple sites on your localhost, ensure that you're in the right database. Also, before deleting anything be sure to create a backup of the DB. Once you've backed up, any table starting with 'cache_' can go. You can individually drop the tables or select the ones you want to get rid of and drop them with a bulk action.

This would, in my case, solve the issue. But, let's take a slightly closer look at the error message to see if we can move beyond using cache clear as some sort of "magical" solution to our problem. It's one thing to fix a problem, it's another to understand it--the latter of these is essential in preventing the problem from happening a second time.

Drupal is obviously looking for an entity type it thinks it should have, but doesn't exist in this database. Since this isn't a fresh install of the module, it's probably not so much the case that the entity type doesn't exist; it's more likely that the name of the entity type was updated to something different from what's in the DB. My Production database is behind my Development database, so it's probably storing the older entity type name. The new entity type name should be found if we can clear a certain cache table and let it be rebuilt.

In this case, we've got a pretty good hint in that verbose error report: we have a Plugin Not Found Exception. Plugins are generally handled by the cache_discovery table, so that's likely where we'll find the root of the problem. I wonder if there's an entry for entity_type in the cache_discovery table? Let's open up the table and do a quick search:

Searching the cache_discovery table for an entity_type entry
My gut here, was actually to search the cache_discovery table for a google_tag_container entry--that didn't turn up any results. Upon opening the cache_discovery table, however, I immediately noted entries tagged as entity data. Since the error stated that the google_tag_container entity type was not found, the next natural search would be for an entity_type entry.

Lo and behold...

An entry for entity_type appears in our results
An "aha!" moment. What do you think will happen if we delete this sucker?

Here's where it gets really exciting: we have a missing entity type error and we have an entity type entry in cache. I'll cut to the chase: the cache entry is the culprit. If we delete it, our error disappears! Disable verbose error logging and get on with your day.

I imagine few of my readers will have this exact error due to this exact problem. The takeaway here has little to do with the Google Tag Manager module; the takeaway is that if you update your database in one environment and then bring your codebase to another, you may very likely hit this kind of error. When you run that update (i.e.; in DEV), entries in your database are changed. If those entries aren't brought with the codebase to whatever the next environment in your workflow is, Drupal may very well take issue.