2.20.1 - Bug: occasional malformed pages with "th" at start of <body>

Hello,

For a few weeks, seemingly since our update to 2.20.1, I’ve been encountering a issue:

  • “At random”, maybe in 1 of 30 front end page loads on average.
  • Occurs (for me) on multiple computers, networks, and while both logged out and in.

Symptoms:

  • “th” will appear at the top of the page, above the banner. (start of <head>)
  • The <doctype> declaration appears to be missing.
  • About a third of the items from the <head> are instead appended to the start of <body>.
  • General page behavior appears unaffected; nothing is obviously broken.
  • No obvious errors in the browser’s console log.

A rough example, using a copy of the html of the same page in either state:

I’ve been inquiring with other users, and no one I’ve asked as seen it. Others may have seen it, but no one has yet asked me about it.

While working on another issue, I stumbled on this in the AJAX/JS debug (/livewhale/?lw_debug=9):

  • 09-Jul-2025 1:12:28pm CDT LiveWhale Notice: /live/editor/start_editing/profiles/9158 AJAX error: The returned content does not match the expected format: th[ ]… ( details / url / mischlern )
  • 09-Jul-2025 9:49:11am CDT LiveWhale Notice: /live/editor/start_editing/files/437
  • 09-Jul-2025 3:52:11am CDT LiveWhale Notice: /live/editor/start_editing/events/24430
  • 07-Jul-2025 5:22:11pm CDT LiveWhale Notice: /live/editor/start_editing/blurbs/481
  • 02-Jul-2025 1:47:52pm CDT LiveWhale Notice: /live/editor/start_editing/news/6892
  • 01-Jul-2025 6:01:33pm CDT LiveWhale Notice: /live/editor/start_editing/pages/2069
  • 01-Jul-2025 4:25:33pm CDT LiveWhale Notice: /live/editor/start_editing/images/13375
  • 30-Jun-2025 10:57:32am CDT LiveWhale Notice: /live/editor/start_editing/widgets/602
  • 25-Jun-2025 5:38:47pm CDT LiveWhale Notice: /live/editor/start_editing/profiles_type/28
    • Our earliest instances appear to be June 25, one day after our most recent update.

This and other instances appear to correlate to instances that occur while working in the backend/dashboard, affecting multiple types. I also see notices triggered by other editors, suggesting that this isn’t just a issue specific to me.

I’m not certain what functionality this error is referring to for the backend. I suspect something fundamental to LiveWhale but not critical to functionality (i.e. list of item’s history for reversion).

I also suspect that the backend issue is related to the issues observed on the front end, given the overlap of “th”. If so, then the cause is likely to be something that affects any and all pages loaded, or the content it is getting is occasionally malformed. Idk.

Questions:

  • Is anyone else encountering this?
  • If so, any clues or solutions?

Thanks for these diagnostic notes, Nick. I haven’t heard of this arising for anyone else (though, please feel free to speak up if so) – we’ll take a look at reproducing this on our end.

Hi Nick,

Checking with the team, sounds like we sometimes see this once in a blue moon when someone is editing a PHP file and accidentally leaves some bogus text in there (like “th”). We’ve see sometimes like th<?php at the top of a file or some such.

As a debug step, you could try reviewing any custom module code that got edited recently to check for that kind of code typo. Or, if you’re able to find steps to reproduce the error case on dev, you could temporarily disable custom modules by moving them from /modules/ into a folder like /modules_disabled/ or /modules_unused/ to see if the problem persists there. Hope this helps!

Karl

Hello Karl,

That was one of the things I tried when I first noticed the issue. I did make a mistake with a file at the same time and reverted, but it didn’t appear to be related. I also did a quick look for “th” at the head of files at the time, didn’t see anything obvious.

A thought: if it is a typo in a custom module, and assuming I understand the situation, why would the issue appear on both the backend (private) and frontend (public) of the site? Wouldn’t that require an identical typo in two separate files?


That said, I just did a thorough review of the custom modules, and I didn’t find anything obvious. I tried to do a regex approach – th[^A-Za-z] – to also look through the entire file in case it was within a conditional. The appearance of the issue doesn’t seem to match any clear conditional behavior in our modules (i.e. if ‘profiles_edit’ then).

The closest thing I found in my search were two public modules around COVID statistics that involved making tables, or table structures in XML. Lines like:

$tr->insert($xml->th($_LW->setFormatClean($column['column_header'])

I’ve moved these both to a modules.archived folder, in case they were being called unnecessarily and causing issues. I have a feeling these weren’t the cause, though.

I’ll keep an eye out to see if anything has changed.

Thanks,
Nick

Thanks Nick –

A global module would be used in the front-end and back-end, if that’s useful context. Sounds like you’ve already considered that case, but for anybody else encountering a similar issue.

Keep us posted on how it goes, and we’ll stay tuned for any other examples—we’ll see if we’re able to reproduce your current logged examples in the meantime.

Ah, I don’t believe I knew that “global” was an option for modules, good to know.

A quick note: we aren’t using any “global” custom modules in our client folder.

I was able to encounter this on the backend of the site. It appears that the issue causes this error message to appear on the screen: “Whoops, there was an error communicating with the server! Please check your internet connection and try again.”

In the debug log:

11-Jul-2025 11:39:15am CDT LiveWhale Notice: /live/editor/start_editing/profiles/8321 AJAX error: The returned content does not match the expected format: th [ ]… (details / https://www.beloit.edu/livewhale/?profiles_edit_linked&id=8321&tid=3 / mischlern )

I’m not certain, but I think this error occurred asynchronously. I left the profile editor open to talk to someone, then came back to see the “Whoops” error.

This got me thinking: I saw once instance of a user triggering the error multiple times on a single page. From what it appears, this editor opened an event edit page in the morning and left the tab open all day, leading to this:

  • 09-Jul-2025 03:52:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 03:36:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 03:20:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 03:04:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 02:48:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 02:32:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 02:16:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 09-Jul-2025 02:00:11 LiveWhale Notice: /live/editor/start_editing/events/24430
  • continues 20-01
  • 08-Jul-2025 19:54:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 19:38:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 19:22:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 19:06:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 18:50:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 18:34:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 18:18:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 18:02:12 LiveWhale Notice: /live/editor/start_editing/events/24430
  • continues 10-17
  • 08-Jul-2025 09:59:13 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 09:43:13 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 09:27:13 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 08:56:13 LiveWhale Notice: /live/editor/start_editing/events/24430
  • 08-Jul-2025 08:40:13 LiveWhale Notice: /live/editor/start_editing/events/24430

I’ve left a bunch of tabs open to try and “farm” the error, and I was able to trigger it. Like the initial error today: the editor page loaded fine, then had the error occured minutes later.

I’m not sure what the backend page would be trying to do every 20 minutes or so, but it seems related to whatever that may be.

Thanks,
Nick

Thanks Nick – the backend “who is editing this item” script does ping the server every 30sec at that /live/editor/start_editing/{data_type}/{id} endpoint, so that behavior is expected.

The malformed response is interesting – the endpoint is meant to just return an empty json [] or a json warning ['error'=>'<div class="editing-sessions"><strong>Someone else may be editing this '.$term.'.</strong> It\'s been opened in the last few minutes by '.$editors.'...etc...

The endpoint does load the general LW nocache script, though, which I think leaves us in the same spot which is an intermittent bug, error, and/or typo some place not yet located that is affecting something like the onLoad or onOutput action—something that’s popping up places it’s not meant to.

One thought: if you log into dev and leave an editor open there, does the same intermittent bug appear there? Or is it only on prod?

For what it’s worth, I’ve left a profile editor logged-in on one of our test sites and the /live/editor/start_editing/profiles/## AJAX has fired >100 times, always showing the correct [] results. Hard to prove a negative, of course, but I haven’t seen any reproducing of this bug yet.

Hello Karl,

For our dev site, I’ve seen it occur on the frontend. I’ve been working to integrate a new search solution, and I’ve seen it appear on refreshes as I work on styling.

Testing the backend, I’m not seeing any sign that it happened. I’ve have ~30 tabs open with profile edit pages for about an hour, “farming” like I did on prod, and it hasn’t triggered. (To your point, proving negatives…)


This is frustrating, as you can expect. Is it me or the server? Is it us or LiveWhale?

I’m still open to the idea that this is still some errant text in a PHP file somewhere, but it must be a sneaky one. Some questions to help me try and look with more intentionality:

  • What does the “who is editing this item” script use for modules? public or private?

  • Given I see it consistently on frontend, does it seem right to assume it’s a public widget?

  • Any specific handlers should I focus on? (onLoad, onOutput, the “any” kind of handlers?)

  • Assuming a custom module: what are some possibilities that would cause this issue to appear randomly for nearly any request? (Something like “onOutput” would show every load, or if within a conditional, “just events” or similar, right?)

  • Assuming the “th” may have been in client code for some time, only manifesting after the upgrade: do any changes from recent versions seem relevant?

Thanks,
Nick

Thanks Nick,

Sorry this one has been so odd and disruptive!

Since you’re seeing it on dev, I’d suggest a next step is to temporarily disable all custom modules on dev and then see if you’re able to trigger it on a front-end page of dev. If it goes away with the modules removed, that would put the suspicion back on a client module. If it doesn’t, it seems like it’d have to be something else. If you want to share a dev link here where you’re seeing it appear (I’ve clicked around your dev site a bit and haven’t seen it) we can check it out – we’re able to help with browser-based diagnosis here in the forum, we just can’t login/SFTP in to look at files.

At whatever point you feel you’ve exhausted what you want to – and are able to – test on your own, feel free to submit the Request Help Form which will allow us to go hands-on and log in to your prod and dev sites to help track down the issue. Thanks,

Karl

Finally found it at the start of /livewhale/core/config.php/.

"th <?php" in config.php. The pain.

Thinking it was client-related, I didn’t try the core folder until I tried a more robust regex search of the entire site. :upside_down_face: I guess a config file may explain how it was appearing randomly, assuming not every request needs to read the config.

Someone (or something) must have appended it accidentally during our last upgrade. I recall being the one to go in and turn off the editor lockout, so it was likely me.

(That said, unless I was mistaken, I thought I also saw it on dev. Checking dev now, I don’t see it there. Maybe it wasn’t there to begin with, or the automatic upgrade to 2.20.2 remade the config? Who knows; lets just assume I mixed pages up.)

In any case, finally, catharsis after two months trying to chase this down. Thank you again, Karl, for helping work through it.

Hi Nick,

Wow, good catch indeed! Glad you were able to sort this one out. We’re definitely flagging this for our team to be on the lookout for and keep in mind as a place to check in the future.

Thanks for letting us know the culprit and glad that mystery was solved. :mag:

Rachael