The Goodlayers Core PHP 8 Bug That Fills Your Error Log Until the Disk Dies

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_log file in public_html/ (or wp-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

  1. Back up the original theme-option.php first. Rename it to theme-option.php.bak-YYYYMMDD in cPanel File Manager.
  2. Upload the patched file to the same folder.
  3. Verify Theme Options in wp-admin loads and saves without hanging. This is the cleanest test that the fix is working.
  4. Remove the php_flag log_errors off line from .htaccess.
  5. Load a handful of pages and wait a minute. Check public_html/ for a new error_log file. 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.

Scroll to Top