Debugging CMPs -- A Horror Story

I recount a frustrating bug hunt and give some tips on debugging CMPs

I just spent more hours than I care to admit debugging a MODX CMP. I thought I would share a bit about the process, partly because the problem turned out to be so amazingly insidious, and partly because I learned some things that might help you debug a CMP of your own.

While adding CMP features to MyComponent, I created a fairly simple CMP as part of the Example project. The CMP has two tabs: The left one shows a grid with all the Snippets on the site and the right tab shows a Chunk grid.

Every time I rebuilt the project, I would clear the site cache and run the CMP. The snippet grid always showed up empty. The grid was there, but there were no snippets in it. The chunk grid looked fine. I later learned that this only happened right after the cache was cleared, but I'm not sure knowing that would have helped me.

The first thing I did was to put a "Reload" button in the grid's toolbar, which fired this function:

    reloadSnippets: function () {
        this.getStore().baseParams = {
            action: 'mgr/snippet/getList'

That worked fine. All the snippets showed up in the grid every time, which meant that my processor was fine. Looking back, I'm pretty sure that if I had cleared the site cache before clicking on the "Reload" button, it wouldn't have worked, but again, I'm not sure that would have helped.

I spent the next several hours going over the JavaScript code, line by line, in every file I thought might have something to do with the problem. I compared the files with those of a number of other working CMPs. PhpStorm's "Compare Files" was a big help, but I couldn't find anything that looked the least bit suspicious. The snippet grid code was identical to the chunk grid code except for the processor called, and I knew the getlist processor was fine because, a) it worked some of the time, and b) it was essentially identical to the chunk getlist processor.

Next, I got a little desperate and tried various wacky alterations to my JS code, none of which had any effect.

After much too long, I finally got smart and decided to take a look at the process in Chrome's Developer Tools — something I should have done much earlier.

After clearing the site cache, I pressed Ctrl-Shift-I in Chrome and ran the CMP. With the Network tab selected, I could see that everything was executing in the right order, but there was an error in the console:

Uncaught SyntaxError: Unexpected token <

That made me think of the processor, since there were no "<" characters in the JavaScript code (which I knew was free of syntax errors, since PhpStorm didn't find any and the "Reload" button worked). Processors don't show up on Chrome's Network tab, but the Connectors that communicate with them do. I found the call to "connector.php" and clicked on it.

In Chrome's Developer Tools, clicking on a connector file name that has just executed opens up a new section with information on the Ajax request. Everything looked fine on the "Headers" tab. The right processor was being called with the right information. I already knew that it was returning a normal 200 (success) response (from the report on the "Network" tab). When I clicked on the "Response" tab, though, I got a little shock. Here's a partial look at it:

<br />
<font size='1'><table class='xdebug-error' dir='ltr' border='1' cellspacing='0' cellpadding='1'>
<tr><th align='left' bgcolor='#f57900' colspan="5"><span style='background-color: #cc0000; color: #fce94f; font-size: x-large;'>( ! )</span> Notice: Undefined index: gallery.usecss_desc in C:\xampp\htdocs\addons\core\components\gallery\lexicon\en\ on line <i>58</i></th></tr>
<tr><th align='left' bgcolor='#e9b96e' colspan='5'>Call Stack</th></tr>
<tr><th align='center' bgcolor='#eeeeec'>#</th><th align='left' bgcolor='#eeeeec'>Time</th><th align='left' bgcolor='#eeeeec'>Memory</th><th align='left' bgcolor='#eeeeec'>Function</th><th align='left' bgcolor='#eeeeec'>Location</th></tr>

It should have looked something like this:


It looks like gibberish, but I've seen this before. It's an extravagantly formatted E_NOTICE error from PHP. I have E_NOTICE errors turned on in my development environment (I wish every MODX Extra developer did). I had to scroll to the right to see the key part of it. You can also paste the code into a file and look at it in a browser. All the HTML will disappear and you'll see a bright-orange, easy-to-read PHP notice. Here's the important part:

Notice: Undefined index: gallery.usecss_desc

If I scrolled all the way to end of the response, I could see the JSON data that my processor returned. I felt like apologizing to the processor for doubting it.

Using PhpStorm's "Find in Path," I did a search of my entire MODX install (which includes all my Extras) looking for gallery.usecss_desc'. After about 3 seconds, I could see that it only appeared in two places, both (lexicon) files. Clicking on the first search result took me right to the offending line. Here it is, with the previous line for comparison:

$_lang['gallery.thumbzoomcrop_desc'] = 'Whether or not the thumbnail will be zoom-cropped.';
I changed it to this:
$_lang['gallery.usecss_desc'] = '';

The problem with my CMP disappeared. That leaves the question of what Gallery had to do with my CMP. The answer is: absolutely nothing. In fact, as if the error is not weird enough to begin with, according to Package Manager the Gallery plugin is not installed on my site.

Here is my theory (which is my theory — it's a theory, and it's mine) about what was happening. When MODX handles a request and the cache is empty, one of the things it does is load the lexicon. Apparently in some remote part of the MODX brain, the Gallery properties still exist and need lexicon strings, so the left-over Gallery lexicon file got included.

The error in the lexicon file triggered the E_NOTICE error message, which was then lurking in the output buffer, waiting for the request to finish. My processor's output was tacked onto the error message in the buffer and the whole mess got returned to my CMP for processing. When the parser tried to decipher what was supposed to be pure JSON, it just threw up its hands and went out for a beer.

What Have We Learned Here?

First of all, when there is an intermittent problem with a program that makes Ajax requests, see if you can make the problem happen with a developer tool turned on and take a close look at all the connector.php responses. If I had done that, there wouldn't be this pile of pulled-out hair all around my chair.

Second, get yourself a good code editor if you don't have one already. Without PhpStorm, my tribulations would have lasted at least twice as long.

Finally, plugins that are unrelated to the code you are developing can cause some very weird problems in MODX. I've seen this any number of times.

If you're running your code outside of MODX, for example, and you load and initialize MODX, then call any MODX processors, the odds are good that some System Events will fire and some plugins will execute. If the $modx->user and $modx->resource objects don't exist (because your code doesn't create them), things will go south in a hurry and you'll have a devil of a time figuring out why.

Remember the MODX upgrade that changed the hashing method for user passwords? Any plugin that fired on a user save event could crash that install. One of my Extras did that until I fixed it, and if it weren't for a lucky accident, I never would have known about the problem with my Extra.

Even inside of MODX, remember that there are plugins that can step in and modify things whenever you perform a Manager action like saving a Resource, Element, or User. They can interfere with whatever you're trying to do and make your life very miserable for hours on end.

I should mention that most MODX plugins are well-behaved and unlikely to cause any problems, but when everything else fails, start disabling your plugins.

Comments (1)

  1. Susan OttwellJul 16, 2013 at 09:29 PM

    So then this particular problem was caused by Gallery not uninstalling completely, although even if you had the working Gallery installed the error in the lexicon file would still be causing a problem.

    If you discover how to clean Gallery out when uninstalling, it would be a nice thing to know.

Please login to comment.