Skip to content

Frontend fatal when background lazyload CSS references unavailable Lazyload class #1124

Description

@pirate-bot

Summary

Background-image lazy loading can terminate a frontend request with an uncaught Class "OptimoleWP.../Lazyload" not found error.

Expected behavior: Frontend requests continue safely when Optimole cannot load a required background lazy-loading class.

Actual behavior: The request reaches the background lazy-loading CSS path and terminates with the reported class-not-found error.

Impact: Affected pages can render as a fatal error instead of returning their normal frontend response.

Customer context

  • Product / area: Optimole WordPress plugin, frontend background-image lazy loading
  • Version: 4.2.11
  • Environment: WordPress 7.1; PHP 8.1.34 and 8.3.33 in the recorded occurrences
  • Integration / third party: No third-party integration is implicated by the captured plugin frames; one representative request used the Sahifa theme
  • Reported error / symptom: Class "OptimoleWP.../Lazyload" not found from the frontend enqueue path
  • Impact: 2 occurrences across 2 distinct production sites between 2026-08-26 and 2026-08-28

Reproduction notes

Reproduction is inferred from the captured stack trace and source:

  1. Use Optimole 4.2.11 with lazy loading active, without triggering the register_public_actions() guards.
  2. Configure at least one background lazy-load selector so get_background_lazy_css() reaches its marker generation.
  3. Make the plugin's Composer autoloader unavailable or unreadable before Optml_Main::instance() runs.
  4. Load a frontend page that runs wp_enqueue_scripts.

Observed production result: the request terminates at the background CSS generation path with Class "OptimoleWP.../Lazyload" not found. The exact deployed-file condition remains unavailable from telemetry.

Diagnosis

Conclusion

Production telemetry identifies an uncaught missing OptimoleWP\BgOptimizer\Lazyload class error at inc/admin.php:968 during a frontend request. In 4.2.11, startup conditionally includes Composer's autoloader and then continues initialization when that file is unavailable. The frontend background lazy-load CSS path references Lazyload::MARKER directly. The repository evidence therefore confirms that an unavailable Composer loader can produce the captured fatal on the reachable path.

Where this likely occurs

  • Frontend wp_enqueue_scripts flow: inc/admin.phpOptml_Admin::register_public_actions() lines 473-488 registers frontend_scripts() when lazy loading is active and the listed native/video/background configuration guard does not return.
  • Crash location: inc/admin.phpOptml_Admin::get_background_lazy_css() lines 955-969 builds CSS for configured background selectors and references Lazyload::MARKER at line 968.
  • Caller: inc/admin.phpOptml_Admin::frontend_scripts() lines 975-981 invokes get_background_lazy_css() before adding the inline style.
  • Loader boundary: inc/main.phpOptml_Main::instance() lines 95-113 includes vendor/autoload.php only when is_readable() is true, then instantiates Optml_Admin regardless.
  • Class source and intended mapping: inc/v2/BgOptimizer/Lazyload.phpOptimoleWP\BgOptimizer\Lazyload lines 3-15 defines MARKER; composer.json lines 18-24 maps OptimoleWP\ to inc/v2/.
  • Version evidence: tag v4.2.11 is commit e9ee20c5a5e10565d2f8ffc56aa77fe76b202332. inc/admin.php is unchanged from v4.2.10, so the available history does not establish a 4.2.11 regression.

Engineering notes

  • The legacy autoloader in optimole-wp.phpoptml_autoload() lines 24-37 only accepts classes beginning with Optml; it does not provide a fallback for the OptimoleWP\ namespace.
  • The release workflow runs Composer before packaging, and .distignore does not exclude vendor (.github/workflows/deploy.yml lines 16-29; bin/dist.sh lines 16-40; .distignore lines 1-52). This makes an incomplete, inaccessible, or otherwise unavailable deployed Composer loader the supported inference from source, rather than proof that the published archive omitted it.
  • The fatal requires configured background lazy-load selectors because get_background_lazy_css() returns before the static class reference when the selector list is empty. The recorded telemetry does not include the affected sites' file state or exact settings.

Test coverage status

No relevant coverage was found during inspection. A search of tests/ found lazy-load suites including tests/test-lazyload.php and tests/test-lazyload-viewport.php, but no test reference to get_background_lazy_css() or OptimoleWP\BgOptimizer\Lazyload.

What to verify or explore next

  • Reproduce from the 4.2.11 package with its Composer autoloader unavailable, background lazy loading enabled, and at least one background selector configured.
  • Inspect an affected installation's plugin file inventory and PHP readability state for vendor/autoload.php if diagnostic evidence becomes available.
  • Run the existing lazy-load test suites and check whether they exercise the frontend CSS enqueue branch.

Unknowns / follow-up

  • The captured telemetry truncates the class name and does not identify why the Composer autoloader was unavailable on the two sites.
  • No installed-file manifest or deployment history is available for the affected sites.

Confidence

Confidence: 93/100

Production telemetry captures the same uncaught class-loading error twice on distinct sites, and the 4.2.11 source confirms a reachable frontend path that references the namespaced class after startup may continue without its Composer autoloader.

Crash telemetry

Occurrences 2
Distinct sites 2
First seen 2026-08-26 21:33 UTC
Last seen 2026-08-28 22:21 UTC
Crash location product:inc/admin.php:968
Request context frontend
Inside Themeisle SDK no
Product versions 4.2.11
WP versions 7.1
PHP versions 8.1.34, 8.3.33
SDK versions 3.3.58

Source: automated crash report — optimole-wp, fingerprint b80565aa1cbe2030dbc9a43e93d383e8
Generated by bug-report-triage (ID: bug-report-triage_6a9275bea80ec1.52241776)

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions