Kategorie Icon Drupal

Manually Removing Drupal Modules

How to manually remove broken or missing Drupal modules from the database.
Mehr erfahren

How to manually remove broken or missing Drupal modules from the database.
Autor
Paper Boy
Datum
18.Juli 2022

Leftovers from modules that have not been correctly removed from a Drupal installation can cause troubles with your Drupal site in the long run.

Those module leftovers might stick around for a long time unrecognized because they often don't show up on the modules page (/admin/modules) or when running drush pml from the command line. You might even drag those module relicts in your database through a major upgrade. I'll tell you a "funny" story about that further down below.

But where are those leftovers hiding? You might find these relicts of old/unused modules in your config/sync/ dir. There might be yml files with the old module's name, or configs referring to that module. You can find those abandoned modules also when you dig into your database. A good spot to find module leftovers are the tables

  • config / config_export
  • key_value
  • locales_location / locales_source
  • and sometimes the cache tables.

You can use phpMyAdmin to search through all tables of your database to find the module name. Find some screenshots further down.

Another way - if you prefer working on the command line - to find references to missing or corrupted modules is exporting your Drupal database drush sql-dump > mysite.sql and grep for the module's name grep module_system_name mysite.sql. If something shows up, open the database dump in a text editor and search for the module's system name, to see which tables hold relicts of old modules.

Usually I run into that sort of problems when performing a Drupal update and finally run a database update drush updb or when I try to import configs drush cim. The error message, when an import or database update fails, usually tells you, that a module or entity type is missing. The quick solution would be to temporarily download and enable the missing module (composer require drupal/module_name, drush en module_name), then perform the update or config import and finally uninstall and remove the unwanted module again (drush pmu module_name, composer remove drupal/module_name).

But what if you can not simply install the module. It might be incompatible with your current setup or Drupal version or maybe it was a custom module that you can't get hold of. Or it might even be a module with a bad uninstall routine. In any case, you will have to get your hands dirty and manually remove all traces of that module from your databse and/or file system.

Let's dive into an example I encountered today ...

 

I recently composerized a Drupal 8 site (find my detailed howto that explains how to add composer to an existing site in the Drupal docs). The site was manually installed from a tar ball without using composer. After integrating composer into the old Drupal 8 site, I updated from latest Drupal 8 to Drupal 9.3.6 or something. All the way through that process, I did not recognize that I had a blind passenger. Only when updating to 9.4.2 I ran into a problem, caused by that missing module user_points.

$ composer outdated drupal/*
Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/
Info from https://repo.packagist.org: #StandWithUkraine
drupal/captcha                1.2.0        1.3.0        The CAPTCHA module provides this feature to virtually any user facing web form on a Drupal site.
drupal/content_access         1.0.0-alpha3 1.0.0-alpha4 Provides flexible content access control.
drupal/core                   9.3.9        9.4.2        Drupal is an open source content management platform powering millions of websites and applications.
drupal/core-composer-scaffold 9.3.9        9.4.2        A flexible Composer project scaffold builder.
drupal/core-recommended       9.3.9        9.4.2        Locked core dependencies; require this project INSTEAD OF drupal/core.
drupal/image_captcha          1.2.0        1.3.0        Provides an image based CAPTCHA.
drupal/matomo                 1.17.0       1.19.0       Adds Matomo javascript tracking code to all your site's pages.
drupal/metatag                1.19.0       1.21.0       Manage meta tags for all entities.
drupal/metatag_dc             1.19.0       1.21.0       Provides the fifteen <a href="https://dublincore.org/documents/dces/">Dublin Core Metadata Element Set 1.1</a> meta tags from...
drupal/metatag_dc_advanced    1.19.0       1.21.0       Provides forty additional meta tags from the <a href="https://dublincore.org/">Dublin Core Metadata Institute</a>.
drupal/metatag_google_cse     1.19.0       1.21.0       Provides support for meta tags used for Google Custom Search Engine.
drupal/metatag_verification   1.19.0       1.21.0       Verifies ownership of a site for search engines and other services.
drupal/metatag_views          1.19.0       1.21.0       Provides views integration for metatags.

Following the Drupal guide Updating Drupal core via Composer I run:

$ composer update "drupal/core-*" --with-all-dependencies
Loading composer repositories with package information
Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies (including require-dev)
Package operations: 0 installs, 43 updates, 0 removals
  - Updating drupal/core-composer-scaffold (9.3.9 => 9.4.2): Loading from cache
  - Updating symfony/polyfill-php72 (v1.25.0 => v1.26.0): Loading from cache
  - Updating symfony/polyfill-ctype (v1.23.0 => v1.25.0): Loading from cache
  - Updating symfony/polyfill-mbstring (v1.23.1 => v1.25.0): Loading from cache
  - Updating twig/twig (v2.14.11 => v2.15.1): Loading from cache
  - Updating symfony/yaml (v4.4.34 => v4.4.43): Loading from cache
  - Updating symfony/polyfill-php80 (v1.23.1 => v1.25.0): Loading from cache

[...]

Writing lock file
Generating autoload files
46 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
Scaffolding files for drupal/core:
  - Copy [web-root]/.htaccess from assets/scaffold/files/htaccess
  - Copy [web-root]/sites/default/default.settings.php from assets/scaffold/files/default.settings.php

All good so far. Run database updates:

$ drush updb
 -------- ------------------- ------------- ---------------------------------- 
  Module   Update ID           Type          Description                       
 -------- ------------------- ------------- ---------------------------------- 
  image    image_loading_att   post-update   Add the image loading attribute   
           ribute                            setting to image field formatter  
                                             instances.                        
  system   enable_provider_d   post-update   Enable the modules that are       
           atabase_driver                    providing the listed database     
                                             drivers.                          
  update   add_view_update_n   post-update   Add 'view update notifications'   
           otifications_perm                 to roles with 'administer site    
           ission                            configuration'.                   
  views    image_lazy_load     post-update   Add lazy load options to all      
                                             image type field configurations.  
  views    provide_revision_   post-update   Clear caches due to adding a      
           table_relationshi                 relationship from revision table  
           p                                 to base table.                    
 -------- ------------------- ------------- ---------------------------------- 


 Do you wish to run the specified pending updates? (yes/no) [yes]:
> yes

>  [notice] Update started: image_post_update_image_loading_attribute
>  [error]  The "user_points" entity type does not exist. 
>  [error]  Update failed: image_post_update_image_loading_attribute 
 [error]  Update aborted by: image_post_update_image_loading_attribute 
 [error]  Finished performing updates. 

The "user_points" entity type does not exist. Oh well, I think, sounds like some missing module. I'll just quickly install that missing module. But over at the module's project page, I realize that I have some sort of a problem: https://www.drupal.org/project/user_points

user_points Module not supported in D9

I dive into the database to find the version of the module, that has originally been installed on the site and decide to clone the source into my modules dir and try to enable it:

$ git clone https://git.drupalcode.org/project/user_points.git
Klone nach 'user_points' 
remote: Enumerating objects: 128, done.
remote: Total 128 (delta 0), reused 0 (delta 0), pack-reused 128
Empfange Objekte: 100% (128/128), 25.35 KiB | 8.45 MiB/s, fertig.
Löse Unterschiede auf: 100% (53/53), fertig

But when I enable the module, my hope for a quick and dirty fix vanishes:

$ drush en user_points

In ModuleInstaller.php line 123:
                                                                                                     
  Unable to install modules: module 'user_points' is incompatible with this version of Drupal core.  
                                                                                                     

 

 

Removing the module leftovers from the database

After trying to find the easy way out, I decide it's time to dig into the database and manually remove that abandoned module.

 

I use phpMyAdmin to find all references to user_points module in all tables:

phpMyAdmin search through all tables.

This throws a long list of tables holding abandoned entries of the user_points module. I have to admit, I have not spent all too much time with Drupal database schemas, but using my Zen sense I feel that I can easily skip all cache tables and focus on the config and key_value tables. I start with removing the entries from the config table:

Manually remove Drupal module from the database.

Manually remove Drupal module from the database.

 

Let's try it again. Remove caches and perform the database update again.

$ drush cr
 [success] Cache rebuild complete.

$ drush updb
 -------- ------------------- ------------- ---------------------------------- 
  Module   Update ID           Type          Description                       
 -------- ------------------- ------------- ---------------------------------- 
  image    image_loading_att   post-update   Add the image loading attribute   
           ribute                            setting to image field formatter  
                                             instances.                        
  system   enable_provider_d   post-update   Enable the modules that are       
           atabase_driver                    providing the listed database     
                                             drivers.                          
  update   add_view_update_n   post-update   Add 'view update notifications'   
           otifications_perm                 to roles with 'administer site    
           ission                            configuration'.                   
  views    image_lazy_load     post-update   Add lazy load options to all      
                                             image type field configurations.  
  views    provide_revision_   post-update   Clear caches due to adding a      
           table_relationshi                 relationship from revision table  
           p                                 to base table.                    
 -------- ------------------- ------------- ---------------------------------- 


 Do you wish to run the specified pending updates? (yes/no) [yes]:
 > yes

>  [notice] Update started: image_post_update_image_loading_attribute
>  [notice] Update completed: image_post_update_image_loading_attribute
>  [notice] Update started: system_post_update_enable_provider_database_driver
>  [notice] Update completed: system_post_update_enable_provider_database_driver
>  [notice] Update started: update_post_update_add_view_update_notifications_permission
>  [notice] Update completed: update_post_update_add_view_update_notifications_permission
>  [notice] Update started: views_post_update_image_lazy_load
>  [notice] Update completed: views_post_update_image_lazy_load
>  [notice] Update started: views_post_update_provide_revision_table_relationship
>  [notice] Update completed: views_post_update_provide_revision_table_relationship
>  [warning] No configuration objects have been updated.
 [success] Finished performing updates.

Aaaand ... the database update went through, the site is running on Drupal 9.4.2.

 

The lazy site admin could stop here. But for future upgrades' sake, let's find all other references to the module in our database tables and remove them as well. Keep repeating the search with ie. phpMyAdmin until you hit no more user_points occurances. Truncate your cache tables, rebuild your cache (drush cr) and hope for the best when you open your site in your browser.

Good night!

 

 

Credits
Drupal
Körperorientiert
Zurück zur Übersicht