• Hiya! My team recently created an ansible script to deploy out our WordPress servers, mainly to reduce tech debt for our currently very old server. Since then, we’ve been noticing that the Custom CSS is being periodically blown away.

    e.g.,

    mysql> select * from wp_options where option_name like "%frn_wordpress_theme%";
    +-----------+--------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    | option_id | option_name | option_value | autoload |
    +-----------+--------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    | 463 | theme_mods_frn-wordpress-theme | a:6:{i:0;b:0;s:18:"nav_menu_locations";a:4:{s:7:"primary";i:11;s:6:"topbar";i:12;s:11:"footer-left";i:13;s:12:"footer-right";i:14;}s:28:"understrap_posts_index_style";s:7:"default";s:27:"understrap_sidebar_position";s:5:"right";s:25:"understrap_container_type";s:9:"container";s:18:"custom_css_post_id";i:20556;} | yes |
    +-----------+--------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    1 row in set (0.01 sec)

    reverts to

    mysql> select * from wp_options where option_name like "%frn_wordpress_theme%";
    +-----------+--------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    | option_id | option_name | option_value | autoload |
    +-----------+--------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    | 463 | theme_mods_frn-wordpress-theme | a:6:{i:0;b:0;s:18:"nav_menu_locations";a:4:{s:7:"primary";i:11;s:6:"topbar";i:12;s:11:"footer-left";i:13;s:12:"footer-right";i:14;}s:28:"understrap_posts_index_style";s:7:"default";s:27:"understrap_sidebar_position";s:5:"right";s:25:"understrap_container_type";s:9:"container";s:18:"custom_css_post_id";i:-1;} | yes |
    +-----------+--------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
    1 row in set (0.01 sec)

    This theme is a child theme of understrap, and we were not encountering these issues with the old servers.

    There are definitely some differences with our new servers compared to the old. For one, we now have two servers behind a load balancer, rather than a single server. And the latest servers are on PHP 8 vs. PHP 7.

    I’m not quite sure what to make of this – the plugins we have aren’t particularly obscure, and should be compliant with the latest versions of PHP and WordPress. Not to mention they haven’t changed between the servers.

    I’ve validated the CSS we’ve been using, and it doesn’t appear to be blown away by a cron run, including by AMP’s stylesheet verification… so I think the CSS is fine.

    It does appear to be somewhat traffic-related, the value can persist for half an hour when it’s quieter, but a mere minute after we drop a new post to our mailing list.

    We can of course implement the CSS directly in our child theme (and I’ve done so for now), but I’m worried this could suggest there are other odd things happening under the hood messing with our customizations.

    I am most happy to provide more details, I just wanted to get the ball rolling on this topic in case anyone else has encountered this strange behavior. Thank you for your attention.

Viewing 10 replies - 1 through 10 (of 10 total)
  • Hi @mmqqmm

    I think s:18:"custom_css_post_id";i:20556; is being revert to s:18:"custom_css_post_id";i:-1;. This custom_css_post_id field tells WordPress where the Customizer’s Additional CSS is stored. When it’s set to -1, it doesn’t exist for WP, effectively erasing your custom CSS from the front-end.

    Since you are using two servers, the most probable reason I can think of is that your two servers don’t share the same css directory or cache. I would suggest you to try logging what wp_get_custom_css_post() returns on both servers. You may find that one server is returning null, triggering the revert to -1.

    Regards

    Thread Starter mmqqmm

    (@mmqqmm)

    First, I run wp theme mod get custom_css_post_id on both servers

    +--------------------+-------+
    | key | value |
    +--------------------+-------+
    | custom_css_post_id | -1 |
    +--------------------+-------+

    Next, I run this command on one of the servers

    wp option patch update theme_mods_frn-wordpress-theme custom_css_post_id 20556
    and get a success message

    Success: Updated 'theme_mods_frn-wordpress-theme' option.

    If I now run wp theme mod get custom_css_post_id on both servers, I get

    +--------------------+-------+
    | key | value |
    +--------------------+-------+
    | custom_css_post_id | 20556 |
    +--------------------+-------+

    on both servers. Same story running wp eval 'var_dump(wp_get_custom_css_post());' on both servers, both successfully return the database entry for post_id 20556

    Again, both servers share an RDS database, so if one server can access the post with id 20556, the other can too. There must be some other reason this value gets blown away… it’s quite confusing!

    Hi @mmqqmm

    You can use a custom plugin like this to traceout the stack for further diagnose the issue – (put this in plugins/custom-css-plugin-test/custom-css-plugin-test.php)

    <?php
    /**
    * Plugin Name: Custom CSS Plugin Test
    * Description: Logs stack trace when custom_css_post_id changes.
    * Version: 1.0
    */

    define('CCW_EXPECTED_CSS_ID', 20556);

    add_action('init', function () {
    $theme_mods = get_option('theme_mods_' . get_stylesheet());
    $current = isset($theme_mods['custom_css_post_id']) ? $theme_mods['custom_css_post_id'] : null;

    $state_file = plugin_dir_path(__FILE__) . 'last_custom_css_id.txt';
    $last_known = file_exists($state_file) ? (int)trim(file_get_contents($state_file)) : null;

    if ($current !== CCW_EXPECTED_CSS_ID && $current !== $last_known) {
    $time = date('c');
    $trace = wp_debug_backtrace_summary();

    error_log("[CCW] ALERT: custom_css_post_id changed to $current at $time");
    error_log("[CCW] Stack trace: $trace");

    // Update the state file
    file_put_contents($state_file, $current);
    } elseif ($current === CCW_EXPECTED_CSS_ID && $current !== $last_known) {
    // Value restored
    file_put_contents($state_file, $current);
    }
    });

    First make sure debug logging is true in your wp-config.php file. Then activate this plugin and visit some pages in your website, create a post (basically try to replicate the action which is triggering the custom css reset behaviour). Check the debug.log file (in wp-content) and paste its content here.

    Regards

    Thread Starter mmqqmm

    (@mmqqmm)

    Thank you for your attention and suggestions Sandeep.

    I’m unclear if this is fully working.. or at least now excludes some possible reasons for this. I’ve modified this code for more illumination:

    add_action('init', function () {
    $theme_mods = get_option('theme_mods_' . get_stylesheet());
    $current = isset($theme_mods['custom_css_post_id']) ? $theme_mods['custom_css_post_id'] : null;

    $state_file = plugin_dir_path(__FILE__) . 'last_custom_css_id.txt';
    $last_known = file_exists($state_file) ? (int)trim(file_get_contents($state_file)) : null;

    $time = date('c');
    $trace = wp_debug_backtrace_summary();

    error_log("[CCW] ALERT: custom_css_post_id changed to $current (from $last_known ?) at $time");
    error_log("[CCW] Stack trace: $trace");


    if ($current !== $last_known) {
    // Update the state file
    error_log("[CCW] ALERT: updating value in file from $last_known to $current");
    file_put_contents($state_file, $current);
    }
    });

    This is what I see in the debug file

    [14-Jul-2025 19:27:59 UTC] [CCW] ALERT: custom_css_post_id changed to -1 (from -1 ?) at 2025-07-14T19:27:59+00:00
    [14-Jul-2025 19:27:59 UTC] [CCW] Stack trace: include('phar:///usr/local/bin/wp/php/boot-phar.php'), include('phar:///usr/local/bin/wp/vendor/wp-cli/wp-cli/php/wp-cli.php'), WP_CLI\bootstrap, WP_CLI\Bootstrap\LaunchRunner->process, WP_CLI\Runner->start, WP_CLI\Runner->load_wordpress, require('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, WP_CLI\Runner->{closure}

    I DO see the value in last_custom_css_id.txt changing, but the final error statement is NOT changing.

    However, to note, I have a DIFFERENT function I created for this debugging process in functions.php

    add_action('updated_option', function($option_name, $old_value, $value) {
    if ($option_name === 'theme_mods_frn-wordpress-theme') {
    $old_data = maybe_unserialize($old_value);
    $new_data = maybe_unserialize($value);

    $old_css_id = isset($old_data['custom_css_post_id']) ? $old_data['custom_css_post_id'] : 'not set';
    $new_css_id = isset($new_data['custom_css_post_id']) ? $new_data['custom_css_post_id'] : 'not set';

    if ($old_css_id !== $new_css_id) {
    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
    $caller_info = [];
    foreach ($trace as $frame) {
    if (isset($frame['file']) && isset($frame['line'])) {
    $caller_info[] = basename($frame['file']) . ':' . $frame['line'];
    }
    }

    error_log("CUSTOM_CSS_RESET: Changed from {$old_css_id} to {$new_css_id}");
    error_log("CUSTOM_CSS_RESET: Backtrace: " . implode(' -> ', $caller_info));
    }
    }
    }, 10, 3);

    And I DO note that I see the logging of the change happening in the debug file from this function

    [14-Jul-2025 19:28:00 UTC] CUSTOM_CSS_RESET: Changed from -1 to 20556
    [14-Jul-2025 19:28:00 UTC] CUSTOM_CSS_RESET: Backtrace: class-wp-hook.php:324 -> class-wp-hook.php:348 -> plugin.php:517 -> option.php:1031 -> Option_Command.php:739 -> CommandFactory.php:100 -> Subcommand.php:497 -> Runner.php:470

    I wonder if this timeframe suggests anything? I don’t see the debug lines prefaced by [CCW] being called when the switch-back happens, only when I explicitly call the CLI.

    Thread Starter mmqqmm

    (@mmqqmm)

    To further note, I see some logging in /var/log/nginx/error.log with these CCW lines, and near them I see the following (with some redaction and consolidation of what appears to be extraneous info

    2025/07/14 21:45:42 [error] 442968#442968: *7342 FastCGI sent in stderr: "e():175-->; PHP message: 2; PHP message: 1752529542.7571-includes/helpers.php@wphp_is_applicable():175-->; PHP message: 2; PHP message: WordPress database error MySQL server has gone away for query SELECT   wp_posts.*
    FROM wp_posts LEFT JOIN wp_postmeta c ON wp_posts.ID = c.post_id and c.meta_key like '_wplp_%' and (( wp_posts.post_type in ('post','page') and c.meta_key not like "_wplp_") OR ( wp_posts.post_type='page' and (c.meta_key in ( '_wplp_hide_frontpage') )))
    WHERE 1=1 AND wp_posts.post_type = 'acf-post-type' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled')) AND c.post_id IS NULL

    ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC
    made by require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, ACF->init, do_action('acf/init'), WP_Hook->do_action, WP_Hook->apply_filters, ACF_Post_Type->register_post_types, ACF_Internal_Post_Type->get_posts, ACF_Internal_Post_Type->get_raw_posts, get_posts, WP_Query->qu...; PHP message: [CCW] ALERT: custom_css_post_id changed to 20556 (from 20556 ?) at 2025-07-14T21:45:42+00:00; PHP message: [CCW] Stack trace: require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, {closure}; PHP message: WordPress database error MySQL server has gone away for query SELECT * FROM wp_redirection_items WHERE match_url IN ('/mailman/listinfo.cgi', '/mailman/listinfo.cgi', 'regex') AND status='enabled' LIMIT 20000 made by require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, WordPress_Module->init, Red_Item::get_for_url, Red_Item::get_for_matched_url, w
    2025/07/14 21:45:43 [error] 442968#442968: *7342 FastCGI sent in stderr: "ype in ('post','page') and c.meta_key not like "_wplp_") OR ( wp_posts.post_type='page' and (c.meta_key in ( '_wplp_hide_frontpage') )))
    WHERE 1=1 AND wp_posts.post_type = 'popup' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')) AND c.post_id IS NULL

    ORDER BY wp_posts.post_modified DESC
    made by require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/frn-wordpress-theme/404.php'), get_header, locate_template, load_template, require_once('/themes/frn-wordpress-theme/header.php'), get_template_part, locate_template, load_template, require('/themes/frn-wordpress-theme/inc/wp-head.php'), wp_head, do_action('wp_head'), WP_Hook->do_action, WP_Hook->apply_filters, wp_enqueue_scripts, do...; PHP message: WordPress database error MySQL server has gone away for query SELECT COUNT(*)
    FROM wp_comments
    WHERE ( comment_approved = '1' )


    made by require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/frn-wordpress-theme/404.php'), get_header, locate_template, load_template, require_once('/themes/frn-wordpress-theme/header.php'), get_template_part, locate_template, load_template, require('/themes/frn-wordpress-theme/inc/wp-head.php'), wp_head, do_action('wp_head'), WP_Hook->do_action, WP_Hook->apply_filters, wp_enqueue_scripts, do_action('wp_enqueue_scripts'), WP_Hook->do_action, WP_Hook->apply_filters, Thrive_Comments_Front->enqueue_scripts, Thrive_Comments_Front->tcm_show_comments, get_comment_count, get_comments, WP_Comment_Query->query, WP_Comment_Query->get_comments, WP_Comment_Query->get_comment_ids, wpdb->get_var, wpdb->print_error; PHP message: WordPress database error MySQL server has gone away for query SELECT COUNT(*)
    FROM wp_comments
    WHERE ( comment_approved = '0' )


    made by require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), in

    I see database errors like this somewhat regularly in the logs… but they only seem to have the format like the above (a call to wp_posts and then a call to wp_redirection_items ) when the value switches back.

    Here’s a call a log with a similar error that didn’t trigger a switch of the custom post ID

    2025/07/14 22:25:39 [error] 439497#439497: *11904 FastCGI sent in stderr: "e():175-->; PHP message: 2; PHP message: 1752531935.7558-includes/helpers.php@wphp_is_applicable():175-->; PHP message: 2; PHP message: WordPress database error MySQL server has gone away for query SELECT   wp_posts.*
    FROM wp_posts LEFT JOIN wp_postmeta c ON wp_posts.ID = c.post_id and c.meta_key like '_wplp_%' and (( wp_posts.post_type in ('post','page') and c.meta_key not like "_wplp_") OR ( wp_posts.post_type='page' and (c.meta_key in ( '_wplp_hide_frontpage') )))
    WHERE 1=1 AND wp_posts.post_type = 'acf-post-type' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'acf-disabled')) AND c.post_id IS NULL

    ORDER BY wp_posts.menu_order ASC, wp_posts.post_title ASC
    made by require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, ACF->init, do_action('acf/init'), WP_Hook->do_action, WP_Hook->apply_filters, ACF_Post_Type->register_post_types, ACF_Internal_Post_Type->get_posts, ACF_Internal_Post_Type->get_raw_posts, get_posts, WP_Query->qu...; PHP message: [CCW] ALERT: custom_css_post_id changed to 20556 (from 20556 ?) at 2025-07-14T22:25:35+00:00; PHP message: [CCW] Stack trace: require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, {closure}; PHP message: WordPress database error MySQL server has gone away for query SELECT * FROM wp_redirection_items WHERE match_url IN ('/blog/guestbook.cgi_237175612', '/blog/guestbook.cgi_237175612', 'regex') AND status='enabled' LIMIT 20000 made by require('wp-blog-header.php'), require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('init'), WP_Hook->do_action, WP_Hook->apply_filters, WordPress_Module->init, Red_Item::get_for_url, Red_Item::get_f
    • This reply was modified 8 months, 2 weeks ago by mmqqmm.
    Thread Starter mmqqmm

    (@mmqqmm)

    All of the above to say… it could be some error with the theme that is conflicting with PHP 8… I’m just not sure what that would be at this time.

    Thread Starter mmqqmm

    (@mmqqmm)

    To follow up more on the above, the theme is a child theme of Understrap and developed in-house. I did some work to fix obvious errors with display, and the site looks identical to the previous now. But there could be more issue with the theme…

    Pulling my question up to a higher-level… does it seem feasible a broken theme could cause issues leading to the custom css value being set?

    e.g., from the console in a browser

    GET
    https://foodrevolution.org/wp-content/themes/frn-wordpress-theme/node_modules/@fortawesome/fontawesome-pro/css/all.css
    NS_ERROR_CORRUPTED_CONTENT

    GET
    https://foodrevolution.org/wp-content/themes/frn-wordpress-theme/node_modules/magnific-popup/dist/magnific-popup.css
    NS_ERROR_CORRUPTED_CONTENT

    GET
    https://foodrevolution.org/wp-content/themes/frn-wordpress-theme/node_modules/magnific-popup/dist/jquery.magnific-popup.js
    NS_ERROR_CORRUPTED_CONTENT

    Uncaught TypeError: jQuery(...).magnificPopup is not a function
    <anonymous> https://foodrevolution.org/wp-content/themes/frn-wordpress-theme/js/child-theme.min.js?ver=0.50.0:1
    • This reply was modified 8 months, 2 weeks ago by mmqqmm.
    Thread Starter mmqqmm

    (@mmqqmm)

    Update: I worked to update our theme and fix the above errors. I did… but CSS is still being blown away.

    Thread Starter mmqqmm

    (@mmqqmm)

    Hey hey, I may have finally discovered a pattern… I see these two lines in the logs when this value gets reset, and not really anywhere else

    2025/07/16 16:02:13 [error] 37636#37636: *30792 FastCGI sent in stderr: "d c.meta_key like '_wplp_%' and (( wp_posts.post_type  in ('post','page') and c.meta_key not like  "_wplp_")  OR ( wp_posts.post_type='page' and (c.meta_key  in ( '_wplp_hide_frontpage')   )))
    WHERE 1=1 AND wp_posts.post_type = 'popup' AND ((wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')) AND c.post_id IS NULL

    ORDER BY wp_posts.post_modified DESC
    made by require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/frn-wordpress-theme/404.php'), get_header, locate_template, load_template, require_once('/themes/frn-wordpress-theme/header.php'), get_template_part, locate_template, load_template, require('/themes/frn-wordpress-theme/inc/wp-head.php'), wp_head, do_action('wp_head'), WP_Hook->do_action, WP_Hook->apply_filters, wp_enqueue_scripts, do...; PHP message: WordPress database error MySQL server has gone away for query SELECT COUNT(*)
    FROM wp_comments
    WHERE ( comment_approved = '1' )


    made by require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/frn-wordpress-theme/404.php'), get_header, locate_template, load_template, require_once('/themes/frn-wordpress-theme/header.php'), get_template_part, locate_template, load_template, require('/themes/frn-wordpress-theme/inc/wp-head.php'), wp_head, do_action('wp_head'), WP_Hook->do_action, WP_Hook->apply_filters, wp_enqueue_scripts, do_action('wp_enqueue_scripts'), WP_Hook->do_action, WP_Hook->apply_filters, Thrive_Comments_Front->enqueue_scripts, Thrive_Comments_Front->tcm_show_comments, get_comment_count, get_comments, WP_Comment_Query->query, WP_Comment_Query->get_comments, WP_Comment_Query->get_comment_ids, wpdb->get_var, wpdb->print_error; PHP message: WordPress database error MySQL server has gone away for query SELECT COUNT(*)
    FROM wp_comments
    WHERE ( comment_approved = '0' )


    made by require('wp-blog-header.php'), re

    Still not sure I understand what is happening here.

    • This reply was modified 8 months, 2 weeks ago by mmqqmm.
    Thread Starter mmqqmm

    (@mmqqmm)

    I really have no idea what’s going on here. I can put the CSS in the child theme directly, but I’m putting a bandaid on some issue that is continuing to happen.

Viewing 10 replies - 1 through 10 (of 10 total)

The topic ‘Custom CSS being blown away’ is closed to new replies.