• Resolved macorak

    (@macorak)


    Hello LiteSpeed team,

    We are experiencing a recurring error in the browser console caused by LiteSpeed Cache (v7.2), related to the delayed loading of JS:

    InvalidCharacterError: Failed to execute ‘setAttribute’ on ‘Element’: ‘=”async”‘ is not a valid attribute name.

    ๐Ÿ” This happens when:

    • Guest Mode is ON
    • Guest Optimization is ON
    • Load JS Deferred / Delayed is enabled (but even when OFF, it can sometimes reappear)
    • QUIC.cloud optimizations are active (UCSS, VPI, Combine JS)

    Weโ€™ve fully purged:

    • All caches (LSC + QUIC.cloud)
    • UCSS, Critical CSS, LQIP, VPI
    • Also disabled Delayed/Deferred scripts, but the error still shows up in certain guest views.

    You can test the issue live here:
    ๐Ÿ‘‰ https://prokese.rs/dugotrajna-platnena-kesa-za-usisivac-karcher-wd2/

    This is causing failing diagnostics in PageSpeed and browser console (especially Chrome and Firefox).

    We believe the issue is due to litespeed_load_delayed_js() attempting to set an attribute incorrectly:
    el.setAttribute(‘=”async”‘)

    โœ… WordPress: 6.8.1
    โœ… LiteSpeed Cache: 7.2
    โœ… WooCommerce + QUIC.cloud Page Optimization: ON

    Please let us know if this is a known bug or if there’s a fix/workaround planned in upcoming releases. We love your plugin and just want to get rid of this console error completely.

    Thank you in advance for your help!

    โ€“ Ljubomir
    https://prokese.rs

Viewing 9 replies - 1 through 9 (of 9 total)
  • Plugin Support litetim

    (@litetim)

    @macorak please share a report ID.
    Report can be created from LSC => Toolbox => Report => click on “Send to Litespeed”

    Thank you for report, I have started debugging it and I need a bit more info to continue.
    I identified something but I want to be sure.

    Thread Starter macorak

    (@macorak)

    Dear LiteSpeed Team,

    ๐Ÿ” We’ve submitted Report ID: IAFMJBMC

    Best regards,
    Ljubomir (prokese.rs)

    Plugin Support litetim

    (@litetim)

    @macorak
    Let’s try this:
    In file public_html/wp-content/plugins/litespeed-cache/src/optimize.cls.php search for '# async(?:=([\'"])(?:[^\1]+)\1)?#isU' (aproximate line 1234) and replace with '# async(?:=['"]async['"])?#is'

    This is not a final solution, take it as a test code, apply it on a stage site OR if you want on live: do it on your own risk.

    Thread Starter macorak

    (@macorak)

    Dear litespeed team,

    i try solution but it break

    There has been a critical error on this website.

    Learn more about troubleshooting WordPress.

    i think better solution is this


    if (strpos($ori, ‘ async’) !== false) {
    $new_ori = preg_replace(‘# async(?:=[“\’]async[“\’])?#is’, ”, $ori);
    if (is_string($new_ori)) {
    $ori = $new_ori;
    }
    }
    i will test it now
    Best regards,
    Ljubomir (prokese.rs)

    Plugin Support litetim

    (@litetim)

    @macorak tell me the results ๐Ÿ™‚
    Try this: # async(?:=([\'"])(?:[^\1]+?)\1)?#is

    The solution will be added to 7.3 ๐Ÿ™‚

    Thread Starter macorak

    (@macorak)

    Hi @litetim,

    Thank you so much โ€” your updated regex works well, but weโ€™ve tested a slightly safer variant that includes a type check to prevent possible null assignment from preg_replace().

    Weโ€™re currently using this in production, and it works like a charm:

    if (strpos($ori, ‘ async’) !== false) {
    $new_ori = preg_replace(‘# async(?:=([\'”])(?:[^\1]+?)\1)?#is’, ”, $ori);
    if (is_string($new_ori)) {
    $ori = $new_ori;
    }
    }

    It gracefully handles any edge cases and prevents the “critical error” that may occur when preg_replace returns null.

    Hereโ€™s the full context inside _js_defer() in optimize.cls.php:

    private function _js_defer( $ori, $src ) {
    if (strpos($ori, ‘ async’) !== false) {
    $new_ori = preg_replace(‘# async(?:=([\'”])(?:[^\1]+?)\1)?#is’, ”, $ori);
    if (is_string($new_ori)) {
    $ori = $new_ori;
    }
    }

    if (strpos($ori, 'defer') !== false) {
        return false;
    }
    if (strpos($ori, 'data-deferred') !== false) {
        Debug2::debug2('[Optm] bypass: attr data-deferred exist');
        return false;
    }
    if (strpos($ori, 'data-no-defer') !== false) {
        Debug2::debug2('[Optm] bypass: attr api data-no-defer');
        return false;
    }
    
    return $ori;

    }

    ๐Ÿง  Just for context, hereโ€™s a quick comparison between your proposed line and our currently used version:

    Your current (proposed) line:
    $ori = preg_replace(‘# async(?:=([\'”])(?:[^\1]+?)\1)?#is’, ”, $ori);

    • โœ… Uses elegant backreference with non-greedy quantifier โ€” much better than the previous version
    • โŒ But has no safeguard against null return from preg_replace()
    • โš ๏ธ This caused a critical error on our site during implementation

    Our current production-safe version:
    if (strpos($ori, ‘ async’) !== false) {
    $new_ori = preg_replace(‘# async(?:=([\'”])(?:[^\1]+?)\1)?#is’, ”, $ori);
    if (is_string($new_ori)) {
    $ori = $new_ori;
    }
    }

    • โœ… Same effective regex
    • โœ… Adds a minimal is_string() check to prevent assignment of null
    • โœ… Already tested live on prokese.rs (WooCommerce, Shoptimizer, LiteSpeed + QUIC.cloud setup)

    Feel free to consider this safe fallback structure for your 7.3 release. Weโ€™d love to see it added so others donโ€™t run into the same edge case.

    Thanks again for your amazing work โ€” happy to contribute!
    ๐Ÿ”ฅ Greetings from the Fenix team โ€” powered by prokese.rs ๐Ÿ’จ

    Plugin Support Hai Zhengโšก

    (@hailite)

    Please try latest dev commit. Is is supposed to be fixed in b21.

    Thread Starter macorak

    (@macorak)

    Thank you very much for your response and for addressing the issue in dev build b21.

    Before your patch was available, we had already implemented a temporary fix to resolve the ="async" error that was causing console issues and affecting PageSpeed “Best Practices” scores.

    Our temporary fix inside the _js_defer() function looked like this:

    if (strpos($ori, ' async') !== false) {
        $ori = preg_replace('# async(?:=["\']async["'])?#is', '', $ori);
    }

    It worked well in practice, especially for the common case where async="async" was being injected, and helped us instantly restore 100/100/100/100 performance scores (especially on Chrome).

    After testing and reviewing your b21 patch:

    $ori = preg_replace('# async(?:=([\'"])(?:[^\1]+)\1)?#isU', '', $ori);

    โ€”we want to say: this is a truly elegant and robust solution. ๐Ÿ™Œ
    It goes beyond simply removing async="async" and properly handles edge cases like async="xyz", with safe, regex-based enforcement of matching quote types. The use of the isU modifiers and non-greedy pattern is especially well thought out.

    Our solution was fast and functional, but yours is long-term, reliable, and production-ready.

    ๐Ÿ‘ Huge respect to your dev team for solving this the right way.

    Weโ€™ll be switching to your implementation as soon as b21 becomes stable and publicly released.

    Thanks again for your support and excellent work.

    Best regards,
    FENIX TEAM
    ๐Ÿ”ฅ๐Ÿ› ๏ธ๐Ÿ•Š๏ธ

    • This reply was modified 10 months, 3 weeks ago by macorak.
    Plugin Support litetim

    (@litetim)

    @macorak the fix will be added in 7.3 Please use that version for live sites.
    Version b21 is for test purposes only, we do not recommand using this on live server.

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

The topic ‘InvalidCharacterError: setAttribute ‘=”async”‘ bug in Gues’ is closed to new replies.