Ask a Jedi: Handling errors in ColdFusion Ajax applications

This post is more than 2 years old.

Shirzad (cool name!) asks:

How do you prevent the Coldfusion Ajax alert message "error retrieving markup..."? Sometimes errors are inevitable. I want to prevent users on our public site from seeing the javascript alert that pops up whenever there's an error in a coldfusion ajax container (or at the very least change the message so it isn't asking people to add cfdebug to the parameters). Is there any way to do this?

There are a couple ways of handling errors with ColdFusion 8's Ajax features. Here is a quick overview of some of them in regards to the cfdiv tag. First, let's make an error. I'll take a simple cfdiv: <cfdiv id="testdiv" bind="url:test2.cfm"/>

And here is test2.cfm:

<cfthrow>

As you can guess, this will immediately throw an error when loaded by the div. The cfdiv tag supports an onBindError attribute. It lets you specify a JavaScript function to run when an error occurs (big surprise there). Here is a modified version of our original script:

<script> function handleError(c,m) { console.log('error '+c+' '+m); } </script>

<cfdiv id="testdiv" bind="url:test2.cfm" onBindError="handleError"/>

The docs specify that the error handler should take two arguments - a status code and message. When I ran this, I correctly saw the error log, but I also saw the 'naked' CF error in the div. I thought perhaps that the onBindHandler would automatically hide the error but it doesn't. I then tried this:

document.getElementById("testdiv").innerHTML = "Error!";

But for some reason, it wouldn't work. I was able to get this to work:

ColdFusion.navigate('/user.cfm','testdiv');

The file user.cfm was just another random file on my server. You would normally point it to a file that had some kind of 'Error' message.

Another option is to specify a global error handler. This is done with the setGlobalErrorHandler:

function handleGError(s) { console.log('global error called '+s); }

ColdFusion.setGlobalErrorHandler(handleGError);

Notice though that this function only takes one argument, a message. I don't know why - but it seems to me as if it should work the same as the error error. Anyway, if you use this, and remove the onBindError, the global error handler will fire.

As yet another example of how you can handle errors, the cfajaxproxy tag has an onError attribute. You can also set a specific error handler for an instance of an AjaxProxy object.

Check the docs for other tags and how they can provide support for this as well. (Consider this my "This your homework" part.) CFGRID for example supports onError which works the same as the onBindError for cfdiv.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Michael de la Morena posted on 9/9/2008 at 10:42 PM

I am using CFAjaxProxy with cfc's and when I call a cfc that has an sql syntax error a page returns to the HTTP request that displays the error. Well the returned page does not get handled like an error because it's status code is 200 and the Response Header does not equal server-error. And since it is not a proper response it does not get sent to the callback handler. What I need to do is handle all possible errors, so that the user is not sitting and waiting for a response when none will ever come. Any ideas?

This is how the cfajax.js determines if a response is an error.

$A.isRequestError=function(req){
return ((req.status!=0&&req.status!=200)||req.getResponseHeader("server-error"));
};

Comment 2 by Raymond Camden posted on 9/9/2008 at 10:46 PM

Ah, so you have CF handling errors as well, which means you get a 'pretty' error.

So here is an idea - use onError to handle the errors, and if the error occurs on an ajax request (you can sniff the request), you could just throw a new exception.

Comment 3 by Henry Ho posted on 9/9/2008 at 10:54 PM

Yes, u can use CFHEADER and send a non 200 HTTP Status Code.

Comment 4 by Paul posted on 9/9/2008 at 11:24 PM

I have a function that is being called through cfajaxproxy that throws a java.lang.NullPointerException with no other detail. But the interesting thing is it only throws the error when called from cfajaxproxy. Invoke it normally through cfinvoke and it works perfectly. I can see that all the parameters are passed fine as they are logged. If I comment out the error handler in the cfc it throws a generic Status: 500 internal server error. Neither error is much help in figuring out what is wrong. Any suggestions as to how I can determine whats causing it would be appreciated.

Comment 5 by Raymond Camden posted on 9/10/2008 at 12:02 AM

Don't test it via cfinvoke. Test it via your browser. Ie, use Firebug to see the URL and paste it into a new tab.

Comment 6 by Paul posted on 9/10/2008 at 12:35 AM

Ray: thanks as always for you prompt response!
That took me right to the line of code that was causing the problem. Excellent! Thank you!

Comment 7 by Shirzad posted on 9/10/2008 at 4:32 AM

Ray: Thanks so much for your help on this - much appreciated. One container I'm still having an issue with is the cflayout-tab. Any ideas how to handle errors that give you the javascript alert from in there (other than a cfcatch)?

Comment 8 by Raymond Camden posted on 9/10/2008 at 5:08 AM

Did you try the global error handler I described above? I haven't tried it for a cflayout error, but I'd give it a shot.

Comment 9 by Shirzad posted on 9/10/2008 at 5:53 PM

Ray: I managed to get the global error handler working for an error in a cfdiv (and even for a cfdiv that's inside a cflayout-tab), but no luck so far with an error in a cflayout-tab. But maybe I'm not doing something right. If anyone can get it to work with a tab, please let me know.

Comment 10 by Raymond Camden posted on 9/11/2008 at 6:54 PM

I got it working. I used the global handler, although cflayoutarea supports onBindError as well. I then gave the tab a name, and was able to use ColdFusion.navigate to send the tab to an error page.

Comment 11 by Shirzad posted on 9/13/2008 at 10:09 PM

OK - thanks Ray. I'll figure out why my code's not working properly. Again, really appreciate your help on this.

Comment 12 by Anthony Patch posted on 1/27/2009 at 8:51 PM

How could I launch a javascript function to display a "pretty" error message if the ajax binding on cfgrid returns a messy JSON error? It seems cfgrid doesn't have an onBindError attribute.
Thanx,
Tony

Comment 13 by Raymond Camden posted on 1/27/2009 at 9:43 PM

Use onError:

<cfgrid autowidth="true" name="entries" format="html" width="600" bind="url:getentries2.cfm?page={cfgridpage}&pagesize={cfgridpagesize}&sort={cfgridsortcolumn}&dir={cfgridsortdirection}" onError="handleError">

Comment 14 by Anthony Patch posted on 1/28/2009 at 6:59 AM

Ray,
That didn't work when there was an AJAX error. It just threw the typical CF javascript popup with alert recommending to turn CFDEBUG on. It didn't call the handleError function. Any ideas what may be happening?
Tony

Comment 15 by Raymond Camden posted on 1/28/2009 at 7:19 AM

What kind of ajax error? I'd say _any_ error in loading the data is an ajax error.

Comment 16 by Kumar posted on 6/25/2014 at 5:49 PM

Ray, Sorry for resurrecting years old post, but I was looking for a solution similar to what's posted here. I have a cfm module that uses cfgrid to call a cfc module to get the data. If for some reason the data is not available, currently cf throws the cfc error (..recommending to turn cfdebug on). Is there a nicer way to handle error messages? I did see a similar post above where you said to use "onerror="handleError"" but that doesn't seem to work well. When I add the onerror the page falls apart. Here is the piece of code where i added onerror -
<cfset args.bind = "cfc:pagination.casetransbind.getCaseTrans({cfgridpage},{cfgridpagesize}, {cfgridsortcolumn},{cfgridsortdirection}, #case_tmp#)"
onError="ErrorRoutine">
Any idea what I'm doing wrong?

Comment 17 by Raymond Camden posted on 6/25/2014 at 5:50 PM

When you say the data is not available, do you mean the DB is down, or you are returning 0 items back? Because 0 items back should work just fine.

Comment 18 by Kumar posted on 6/25/2014 at 6:13 PM

Well, to elaborate the data, I'm parsing an XML file that is returned from Cobol module and building a query in cfc and then returning the data back to cfm using QueryConvertForGrid. For example, I entered case number, and if the case has any detail info, it returns the detail info nodes in the XML. Otherwise DB2 returns only the basic info. When detail info node is not available, CFC throws the error. In CFC, I'm looking for that detail info node. I'm also checking for the node existence in cfc and if not available, throw error message. But I'm not sure if I'm doing it right for cfgrid to capture that error. so here is the error capture in cfc -
<cfif Not IsDefined("DetailNode")> <cfset err_msg = Insert("#AppErrorMsg#<br />", err_msg, Len(err_msg))> <cfreturn err_msg></cfif>.

Comment 19 by Raymond Camden posted on 6/25/2014 at 6:18 PM

Well wait - do you want the grid to show a friendly error, or just no data? If you just want to to show no data, handle the error in your CFC and return an empty record set.

Comment 20 by Kumar posted on 6/25/2014 at 6:24 PM

I would like to grid to show a friendly error instead of an empty grid. Like 'No detail records found". I think I'm handling the error in CFC but it doesn't seems to be appearing on the grid. If I take off the onerror function, I get "DetailNode is undefined in the XML with cfdebug info" popup message. Instead of that popup message, would like to display it on the grid.

Comment 21 by Raymond Camden posted on 6/25/2014 at 6:26 PM

Can't help you there - sorry. I don't use cfgrid, nor do I recommend anyone else use it. That doesn't help you, but I'd rather tell you that then nothing at all. ;)

Comment 22 by Kumar posted on 6/25/2014 at 6:31 PM

Thanks. When you are saying you don't recommend cfgrid, what other ways do you recommend. I'm flexible if you have other recommendations.

Comment 23 by Raymond Camden posted on 6/25/2014 at 6:41 PM

Read these entries: http://www.raymondcamden.co...

Comment 24 by Kumar posted on 7/7/2014 at 7:22 PM

Ray, just wanted to circle back to this issue and let you or anyone who is interested know i did the following steps as a work around -
My first mistake was on the CFC page i was returning the error messages by using cfreturn. I should know better. Anyway, changed that to cfthrow.
Second on the CFM page, I wrote a javascript module that is expecting two parms (status, text). And display the text using innerhtml to display it on the screen instead of cf default popup message with cfdebug in it.
Third - I'm calling the javascript from cfgrid onerror event.
That worked for me.