A WordPress maintenance war story, with the exact one-line fix.
Is this you?
Your WordPress site running a Goodlayers GEN3 theme has started behaving oddly. The signs, in roughly the order they show up:
- A new
error_logfile inpublic_html/(orwp-admin/) growing alarmingly fast. We saw 500MB per minute on a 10GB host. The disk fills in under twenty minutes. - The Theme Options panel in wp-admin loads, but hangs forever when you try to save.
- The WordPress Customizer starts hanging too, and edits stop sticking.
- Inside the error log, the same warning repeated thousands of times per second:
PHP Warning: Undefined array key "sub-menu-shadow-size>t rgba(0, 0, 0, <sub-menu-shadow-opacity>t); -webkit-box-shadow: 0px 0px <sub-menu-shadow-size>t rgba(0, 0, 0, <sub" in /wp-content/plugins/goodlayers-core/framework/function/theme-option.php on line 354
If that pattern matches, this article will save you a panicked night.
What’s happening, in plain English
Goodlayers stores CSS templates with placeholder tokens like <sub-menu-shadow-size>. When the page loads, the plugin walks through these templates and swaps the placeholders for the actual values you have set in Theme Options.
That walk has a bug. When a CSS selector contains a > symbol before the placeholder, the plugin gets confused about which > belongs to the placeholder. It picks the wrong one, extracts a giant nonsense string instead of the placeholder name, then tries to look that nonsense up in the options array. The lookup fails, PHP logs a warning, and because the same code runs on every page load (and many times per page), the warning fires thousands of times per second.
The > symbol in CSS is the “child combinator”, written like .menu > .submenu. It is extremely common in CSS selectors. So once the trigger conditions are met, the bug fires constantly.
This bug has probably been in Goodlayers Core for years. It only became visible when your host upgraded to PHP 8.
Why PHP 8 changes things
PHP 7 quietly ignored failed array lookups. PHP 8 promotes them to a Warning, which gets written to the error log. Same buggy code, dramatically different consequences.
Many shared hosts have been migrating customers to PHP 8 over the last twelve months. If your site was happy on PHP 7.4 last year and is now flooding the disk, this is the most likely culprit.
You cannot simply roll back to PHP 7.4 as a permanent fix. PHP 7.4 is end of life. Security plugins, payment gateways and other modern code will start to break on it.
What to do if you are a site owner
You need someone comfortable editing PHP plugin files and using cPanel File Manager or SFTP. If that is not you, the steps below are what to hand to the developer you call.
In the meantime, your immediate priority is to stop the error log from filling the disk. Add this line to the very top of public_html/.htaccess:
php_flag log_errors off
That suppresses the log file growth and buys you breathing room. It is a temporary measure, not a fix. Real PHP errors will also be hidden while it is in place.
Once the disk pressure is relieved, delete the runaway error_log file (it can be hundreds of megabytes or several gigabytes).
Then arrange for someone to apply the patch below.
The fix, for developers
The file to edit is:
wp-content/plugins/goodlayers-core/framework/function/theme-option.php
There are three lines to change. All of them are strpos calls that need a fourth argument so the search starts at the position of the opening <, rather than from the start of the string.
Line 344
Change:
php
$end_extra = strpos($option['selector'], '>');
To:
php
$end_extra = strpos($option['selector'], '>', $start_extra);
Line 345
Change:
php
$end_alpha = strpos($option['selector'], '>a');
To:
php
$end_alpha = strpos($option['selector'], '>a', $start_extra);
Line 447
Slightly different because the surrounding code does not guarantee $start_extra is set. Change:
php
$end_extra = strpos($option['selector'], '>');
To:
php
$end_extra = strpos($option['selector'], '>', $start_extra !== false ? $start_extra : 0);
That is the whole patch.
What it does
Each strpos call now searches for > from the position of the opening < onwards. A > that appears earlier in the selector (a CSS child combinator) can no longer be mistaken for the placeholder’s closing bracket. The substring extraction stays clean and the array lookup succeeds.
Installation
- Back up the original
theme-option.phpfirst. Rename it totheme-option.php.bak-YYYYMMDDin cPanel File Manager. - Upload the patched file to the same folder.
- Verify Theme Options in wp-admin loads and saves without hanging. This is the cleanest test that the fix is working.
- Remove the
php_flag log_errors offline from.htaccess. - Load a handful of pages and wait a minute. Check
public_html/for a newerror_logfile. None should appear, or if one does, it should be tiny and contain unrelated content.
Important caveat
If Goodlayers Core is ever updated, the patch will be overwritten and the bug will return. Make a backup of the patched file and document the change somewhere your future self will find it. Many sites running Goodlayers GEN3 sit on a frozen plugin version (no licence, no auto-updates) so in practice the patch tends to be permanent, but it is worth knowing.
Why this matters
A typical “my Goodlayers site is broken” diagnosis ends in a quote for a full rebuild on a modern theme. That is sometimes the right call, but it should not be the only call. A site that has worked perfectly for years can be saved with a three-line code change.
If your developer needs more context, or you are stuck and want someone to apply this patch professionally, I am happy to help.
Article by David Appleby, Appleby Design. The exact bug above was diagnosed and patched live on a client’s Goodlayers GEN3 site in May 2026.
