Skip to content

Instantly share code, notes, and snippets.

@lcatlett
Last active July 7, 2025 23:01
Show Gist options
  • Save lcatlett/d609e83eeea3d7c2d98949b93c7b329f to your computer and use it in GitHub Desktop.
Save lcatlett/d609e83eeea3d7c2d98949b93c7b329f to your computer and use it in GitHub Desktop.
Script to fix Drupal Purge dependency issues on Pantheon sites

Drupal Purge Dependency Fix Script

Overview

This script fixes dependency issues related to the Purge and Acquia Purge modules in Drupal sites hosted on Pantheon. It's particularly useful when you encounter errors like:

The service "acquia_purge.tagsheaders.cacheable_response_subscriber" has a dependency on a non-existent service "purge.tagsheaders".

or

You have requested a non-existent service "purge.queuers".

These errors typically occur when migrating from Acquia to Pantheon, or when the Purge module is uninstalled improperly, leaving behind service references that break the Drupal container.

Features

  • Multiple repair approaches (Drush API and direct SQL)
  • Progressive escalation from gentle fixes to aggressive solutions
  • Comprehensive module removal from core.extension and system.schema
  • Thorough cache clearing using multiple methods
  • "Nuclear option" for stubborn cases
  • Site verification after fixes

Requirements

  • Terminus CLI installed and authenticated
  • Access to the Drupal site on Pantheon
  • Bash shell environment

Usage

./fix-purge-dependency.sh [site-name] [environment]

Parameters

  • site-name: The Pantheon site name (defaults to "site-name" if not provided)
  • environment: The Pantheon environment (defaults to "live" if not provided)

Examples

# Fix purge dependency issues on the live environment of site-name
./fix-purge-dependency.sh site-name live

# Fix purge dependency issues on the dev environment of site-name
./fix-purge-dependency.sh site-name dev

# Use default site-name and environment (site-name.live)
./fix-purge-dependency.sh

How It Works

The script follows a progressive approach to fixing the issue:

  1. Drush API Approach: Attempts to use Drupal's API to remove problematic modules
  2. SQL Approach: Directly modifies database tables to remove module references
  3. Cache Clearing: Truncates cache tables to force rebuilding of container
  4. Service Provider Cleanup: Removes service provider entries directly
  5. Nuclear Option: Removes all purge-related configuration from the database

Troubleshooting

If the script fails to fix the issue:

  1. Check the Pantheon logs for more detailed error messages
  2. Try running the script with the default site name and environment
  3. Consider restoring the site from a backup if all repair attempts fail
  4. Contact Pantheon support for assistance with persistent issues

License

MIT License

Author

Lindsey Catlett

#!/bin/bash
# Drupal Purge Dependency Fix Script
# This script fixes dependency issues related to the Purge and Acquia Purge modules
# in Drupal sites hosted on Pantheon.
#
# Author: Lindsey Catlett
# License: MIT
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Site and environment to fix
SITE_NAME=${1:-site-name}
SITE_ENV=${2:-live}
echo -e "${BLUE}🔧 Fixing purge dependency issues for $SITE_NAME.$SITE_ENV${NC}"
# Step 1: Check if we can access the site
echo -e "${YELLOW}Step 1: Checking site access...${NC}"
if ! terminus site:info "$SITE_NAME" &>/dev/null; then
echo -e "${RED}❌ Cannot access site $SITE_NAME. Please check the site name and your Terminus authentication.${NC}"
exit 1
fi
# Step 2: Try Drush approach first (might work if container is not completely broken)
echo -e "${YELLOW}Step 2: Attempting to fix with Drush commands...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- ev "
// Try to access the container - this might fail
try {
// Get the container builder
\$container = \Drupal::getContainer();
// Check if the problematic services exist
\$problematicServices = [
'acquia_purge.tagsheaders.cacheable_response_subscriber',
'purge.queuers',
'purge.tagsheaders',
'purge.purgers',
'purge.queue',
'purge.processors'
];
\$foundProblematic = false;
foreach (\$problematicServices as \$service) {
if (\$container->has(\$service)) {
echo \"Found problematic service: {\$service}\\n\";
\$foundProblematic = true;
}
}
if (\$foundProblematic) {
echo 'Removing purge-related modules from core.extension...\n';
// Remove purge-related modules from core.extension
\$config = \Drupal::configFactory()->getEditable('core.extension');
\$modules = \$config->get('module');
// List of all purge-related modules to remove
\$purgeModules = [
'acquia_purge',
'purge',
'purge_queuer_url',
'purge_drush',
'purge_processor_cron',
'purge_processor_lateruntime',
'purge_tokens',
'purge_ui',
'purge_queuer_coretags',
'purge_tagsheaders'
];
foreach (\$purgeModules as \$module) {
if (isset(\$modules[\$module])) {
unset(\$modules[\$module]);
echo \"Removed {\$module} from core.extension\\n\";
}
}
\$config->set('module', \$modules)->save();
echo 'Saved core.extension changes\n';
// Remove from system.schema to prevent update hooks
\$keyValue = \Drupal::keyValue('system.schema');
foreach (\$purgeModules as \$module) {
\$keyValue->delete(\$module);
echo \"Removed {\$module} from system.schema\\n\";
}
// Clear all caches that might store service information
\$caches = [
'bootstrap' => ['bootstrap_container_service_providers'],
'discovery' => ['*'],
'container' => ['*']
];
foreach (\$caches as \$bin => \$cids) {
\$cache = \Drupal::cache(\$bin);
if (in_array('*', \$cids)) {
\$cache->deleteAll();
echo \"Cleared all caches in {\$bin} bin\\n\";
} else {
foreach (\$cids as \$cid) {
\$cache->delete(\$cid);
echo \"Cleared {\$cid} cache in {\$bin} bin\\n\";
}
}
}
}
} catch (Exception \$e) {
echo \"Drush approach failed: {\$e->getMessage()}\\n\";
echo \"Will try SQL approach next.\\n\";
}
" || echo "Drush approach failed, will try SQL approach next."
# Step 3: Direct SQL approach to remove purge modules from core.extension
echo -e "${YELLOW}Step 3: Removing purge modules from core.extension table using SQL...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
-- Get current core.extension data
SELECT data INTO @current_data FROM config WHERE name = 'core.extension';
-- Remove purge modules from the serialized data
-- This is a bit hacky but necessary when the container is broken
SET @current_data = REPLACE(@current_data, 's:12:\"acquia_purge\";i:', 's:12:\"acquia_purge\";N;');
SET @current_data = REPLACE(@current_data, 's:5:\"purge\";i:', 's:5:\"purge\";N;');
SET @current_data = REPLACE(@current_data, 's:16:\"purge_queuer_url\";i:', 's:16:\"purge_queuer_url\";N;');
SET @current_data = REPLACE(@current_data, 's:11:\"purge_drush\";i:', 's:11:\"purge_drush\";N;');
SET @current_data = REPLACE(@current_data, 's:19:\"purge_processor_cron\";i:', 's:19:\"purge_processor_cron\";N;');
SET @current_data = REPLACE(@current_data, 's:25:\"purge_processor_lateruntime\";i:', 's:25:\"purge_processor_lateruntime\";N;');
SET @current_data = REPLACE(@current_data, 's:12:\"purge_tokens\";i:', 's:12:\"purge_tokens\";N;');
SET @current_data = REPLACE(@current_data, 's:8:\"purge_ui\";i:', 's:8:\"purge_ui\";N;');
SET @current_data = REPLACE(@current_data, 's:20:\"purge_queuer_coretags\";i:', 's:20:\"purge_queuer_coretags\";N;');
SET @current_data = REPLACE(@current_data, 's:17:\"purge_tagsheaders\";i:', 's:17:\"purge_tagsheaders\";N;');
-- Update the config table with modified data
UPDATE config SET data = @current_data WHERE name = 'core.extension';
"
# Step 4: Remove entries from system.schema table
echo -e "${YELLOW}Step 4: Removing purge modules from system.schema table using SQL...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
DELETE FROM key_value
WHERE collection = 'system.schema'
AND name IN (
'acquia_purge',
'purge',
'purge_queuer_url',
'purge_drush',
'purge_processor_cron',
'purge_processor_lateruntime',
'purge_tokens',
'purge_ui',
'purge_queuer_coretags',
'purge_tagsheaders'
);
"
# Step 5: Truncate all cache tables
echo -e "${YELLOW}Step 5: Truncating all cache tables...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
SHOW TABLES LIKE 'cache%'
" | while read table; do
echo "Truncating $table..."
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "TRUNCATE TABLE $table;"
done
# Step 6: Try to clear cache again
echo -e "${YELLOW}Step 6: Attempting to clear all caches...${NC}"
if terminus drush "$SITE_NAME.$SITE_ENV" -- cr; then
echo -e "${GREEN}✅ Successfully cleared all caches${NC}"
else
echo -e "${YELLOW}⚠️ Cache rebuild still has issues. Trying more aggressive approach...${NC}"
# Step 7: More aggressive approach - delete service provider entries directly
echo -e "${YELLOW}Step 7: Removing service provider entries directly...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
-- Delete service provider entries from bootstrap cache
DELETE FROM cache_bootstrap WHERE cid = 'bootstrap_container_service_providers';
-- Delete container definition
DELETE FROM cache_container WHERE cid LIKE '%container%';
-- Delete discovery cache
TRUNCATE cache_discovery;
"
# Try cache rebuild one more time
echo -e "${YELLOW}Step 8: Second attempt to clear caches...${NC}"
if terminus drush "$SITE_NAME.$SITE_ENV" -- cr; then
echo -e "${GREEN}✅ Successfully cleared all caches after removing service providers${NC}"
else
echo -e "${YELLOW}⚠️ Cache rebuild still failing. Trying direct database manipulation...${NC}"
# Step 9: Direct database manipulation
echo -e "${YELLOW}Step 9: Direct database manipulation...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
-- Remove all service definitions that might reference purge
DELETE FROM cache_discovery WHERE cid LIKE '%purge%';
DELETE FROM cache_container WHERE cid LIKE '%purge%';
-- Ensure the modules are really gone from core.extension
UPDATE config SET data = REPLACE(data, 'acquia_purge', 'acquia_purge_disabled') WHERE name = 'core.extension';
UPDATE config SET data = REPLACE(data, 'purge', 'purge_disabled') WHERE name = 'core.extension';
-- Clear all caches one more time
TRUNCATE cache_bootstrap;
TRUNCATE cache_config;
TRUNCATE cache_container;
TRUNCATE cache_data;
TRUNCATE cache_default;
TRUNCATE cache_discovery;
TRUNCATE cache_dynamic_page_cache;
TRUNCATE cache_entity;
TRUNCATE cache_menu;
TRUNCATE cache_render;
TRUNCATE cache_toolbar;
"
# Try cache rebuild one more time
echo -e "${YELLOW}Step 10: Third attempt to clear caches...${NC}"
if terminus drush "$SITE_NAME.$SITE_ENV" -- cr; then
echo -e "${GREEN}✅ Successfully cleared all caches after direct database manipulation${NC}"
else
echo -e "${YELLOW}⚠️ Still having issues. Trying nuclear option...${NC}"
# Step 11: Nuclear option - remove all purge-related config
echo -e "${YELLOW}Step 11: Nuclear option - removing all purge-related config...${NC}"
terminus drush "$SITE_NAME.$SITE_ENV" -- sql-query "
-- Delete all purge-related config
DELETE FROM config WHERE name LIKE '%purge%';
DELETE FROM config WHERE name LIKE '%acquia_purge%';
-- Delete all cache entries that might reference purge
DELETE FROM cache_config WHERE cid LIKE '%purge%';
DELETE FROM cache_config WHERE cid LIKE '%acquia_purge%';
-- Delete all key_value entries that might reference purge
DELETE FROM key_value WHERE name LIKE '%purge%';
DELETE FROM key_value WHERE name LIKE '%acquia_purge%';
-- Clear all caches again
TRUNCATE cache_bootstrap;
TRUNCATE cache_config;
TRUNCATE cache_container;
TRUNCATE cache_data;
TRUNCATE cache_default;
TRUNCATE cache_discovery;
TRUNCATE cache_dynamic_page_cache;
TRUNCATE cache_entity;
TRUNCATE cache_menu;
TRUNCATE cache_render;
TRUNCATE cache_toolbar;
"
# Final cache clear attempt
echo -e "${YELLOW}Step 12: Final attempt to clear caches...${NC}"
if terminus drush "$SITE_NAME.$SITE_ENV" -- cr; then
echo -e "${GREEN}✅ Successfully cleared all caches after nuclear option${NC}"
else
echo -e "${RED}❌ All attempts to fix the issue have failed. Manual database intervention may be required.${NC}"
echo -e "${YELLOW}Suggestion: You may need to restore the site from a backup or contact Pantheon support.${NC}"
exit 1
fi
fi
fi
fi
# Step 13: Verify site is working
echo -e "${YELLOW}Step 13: Verifying site is working...${NC}"
if terminus drush "$SITE_NAME.$SITE_ENV" -- status | grep -q "Drupal bootstrap.*Successful"; then
echo -e "${GREEN}✅ Site is working correctly${NC}"
else
echo -e "${YELLOW}⚠️ Site may still have issues. Please check manually.${NC}"
fi
echo -e "${GREEN}🎉 Purge dependency issues fixed for $SITE_NAME.$SITE_ENV${NC}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment