The Complete Guide to Adding Error Handling to Your ColdFusion Application
I've done more than a few posts recently about error handling and robust exception information, so I thought I'd write up one blog entry that can serve as a nice guide for folks to bookmark. By using "Complete" in the title, I've also virtually assured that I will forget something critical, so please, send suggestions for what I've missed. Let's get started.
What is the point of this guide? Unless you are a perfect code, there is a chance that your ColdFusion application will have errors in it. The question is - what are you doing with your errors? What was the last error that occurred on your site? If I asked you how many errors your site threw yesterday, could you answer with 100% complete accuracy? I'd be willing to bet most people would say no. Shoot, I know I couldn't answer that. So what do we do to help resolve this issue?
The first thing I want you to do is to create an error. Create a new CFM file named errortest.cfm. Insert one line into it:
<cfoutput>#xfhdshsdhj#</cfoutput>
The point of this template is to create an error. Unless you actually have a variable defined with that ugly name, the template will error out. Upload it to your server and run it with your browser.
One of three things will happen:
1) You will get an error with the full path shown, like below. This shows that you have not added error management to your application, and that you have Enabled Robust Exception information in your ColdFusion Administrator. Stop reading this blog entry, go to your Admin, and disable it. Now. (Please note that this guide is intended for a production machine environment. Obviously you can keep this setting on in development. I do.)

2) You will get an error with no path shown. This is slightly better. It still shows that you haven't added error management to your application though.

3) You get an "error page". By "error page" I mean a page saying that an error occurred, but displayed in your standard site layout, or close to it. That's good. You should still continue to read though as I'm going to discuss things that should normally be in an error handler.
Ok, before going on - delete the page you just uploaded. I'd be willing to bet a good 40-50% of us upload test.cfm type files to our servers and forget to delete them. I've never done that. Really.
So - lets talk error handling now. You have two high level options. The first is to set an error template in the ColdFusion administrator:

If you specify a template here, than ColdFusion will run the template when an error occurs. In general though I wouldn't recommend setting the template here.
Your second option - and what I recommend - is to the handle the errors specifically in your application. How? If you are on an older ColdFusion server and only have access to Application.cfm, then you want to the use the CFERROR tag. You can use these tags in Application.cfc as well, but I recommend onError for that. I'm going to cover both though.
A full description of cferror may be found in the docs. I'm going to give you the Ray Camden quickie guide to it. The cferror basically lets you specify an template to run when a type of error occurs. There are 3 main types of errors it monitors: Exception, Request, and Validation. Forget about validation. Don't use it. Exception is the type of error we are most familiar with. It is what I call the 'basic' error. Request is the more serious error. It can occur when your error handler itself screws up. I call this the "Oh S***" error (seriously). It has special restrictions on it I'll discuss in a second. First though, let's look at the syntax you would use in your Application.cfm file:
<cfapplication name="rayrules">
<cferror type="exception" template="error.cfm">
<cferror type="request" template="error_request.cfm">
As you can see - it's pretty simple stuff. I basically said - for the Exception (again, think 'normal' error), run error.cfm. For the Oh Crap error, run error_request.cfm.
If you run any CFM again - you will immediately get an error stating that these files do not exist. You should create blank ones for the time being.
Now for the details. The error.cfm template is a normal CFM page. But it has access to a special variable: ERROR. This variable is a structure that contains a lot of information about the error. What you get there will also depend on the error. SQL errors for example will have different values in the structure than a simple runtime error. Let's just do a quick dump.
<cfdump var="#error#">
If you run your error test again (you may have to reupload it if you deleted it like I suggested, just don't forget to remove it later!), you will see something like this:

I'm not going to list every field - again, check the cferror syntax doc for that. The item you will most care about normal is cferror.message. This is the simplest representation of the error and will be most useful for logging. The diagnostics value gives more detail including a line number which is handy during development.
So what now? Well first off - you probably don't want your public site showing a dump. Let's begin by outputting a nice message to the user. Here is the new version of error.cfm:
We are so sorry. Something went wrong. We are working on it now.
Obviously you can mark that up with nice HTML, use your custom tag layout wrapper, etc. This handles letting the user know something bad happened. At bare minimum, this is better than showing naked errors to the user, but we should do something with the error. I recommend two things.
Log the error. For some odd reason, ColdFusion will nicely log an unhandled error, but will not log a handled error. I believe Blue Dragon logs the error anyway. Since ColdFusion won't log it, we should:
<cflog file="myapperrorlog" text="#error.message# - #error.diagnostics#">
Note that I've specified the message and diagnostics variable. This is a bit of a duplication since diagnostics information will have the same information as message, but I like the shortness of the message value. You could log more than this obviously, but since this is a log file, we don't want to overdue it here.
THe next thing we should do is email the error. This is something I've covered before on the blog, so some of you may know my feelings on this already, but what I typically do is email me the entire error structure. I also include other structures so I can see what else was going on:
<cfsavecontent variable="errortext">
<cfoutput>
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<cfdump var="#error#" label="Error">
<cfdump var="#form#" label="Form">
<cfdump var="#url#" label="URL">
</cfoutput>
</cfsavecontent>
<cfmail to="bugs@myproject.com" from="root@myproject.com" subject="Error: #error.message#" type="html">
#errortext#
</cfmail>
I create my message within a cfsavecontent (more on why in a second), and then mail it. Don't forget the type=html. Now as you can guess, this creates a pretty big email. If you get a 1000 of these, you will be suffering, but consider it incentive to fix the darn bug ASAP. You could also add a dump of the session scope if you wanted, or CGI. Basically, it is better to send more information then you need then to be wanting for more. Having all this detail gives you a better idea of what is going on when the error occurred.
So why the cfsavecontent? One trick I'll often do is to skip the email if I'm currently logged in as an admin on the site. I'll do a quick check, and if I'm an admin, I'll display the error on screen. This lets me see the error more quickly than waiting for an email.
So all together now, here is the error.cfm file:
We are so sorry. Something went wrong. We are working on it now.
<cflog file="myapperrorlog" text="#error.message# - #error.diagnostics#">
<cfsavecontent variable="errortext">
<cfoutput>
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<cfdump var="#error#" label="Error">
<cfdump var="#form#" label="Form">
<cfdump var="#url#" label="URL">
</cfoutput>
</cfsavecontent>
<cfmail to="bugs@myproject.com" from="root@myproject.com" subject="Error: #error.message#" type="html">
#errortext#
</cfmail>
Now for fun, try modifying your error.cfm. Change the first cfdump tag to a cfpoo tag. If you rerun your template, you will see a blank page. Remember that we created a blank error_request.cfm file earlier? This is what is running now. Basically, ColdFusion has noticed that we had an error, and then our error management had an error, and it's thrown it's hands up in the air and given up. We are now in the request template. The request template has special rules - the most important being - no CFML. That's right - you can't cflog. You can't email the error. You can - however - output error variables. You don't use cfoutput, you just include them. Consider this sample:
This went wrong: #error.diagnostics#
This will display:
This went wrong: Unknown tag: cfpoo. ColdFusion cannot determine how to process the tag cfpoo because the tag is unknown and not in any imported tag libraries. The tag name might be misspelled. The error occurred on line -1.
That's all you can do really. But guess what - I wouldn't do that. Remember - we don't want to reveal any sensitive information to our users, including what caused an error. So what do I recommend?
Go to your site and view source. This will give you the HTML result of one of your pages. Find the content and replace it with a "We're sorry" type message like we used in error.cfm. Then save that HTML. Basically you are creating a static page. This means that if you change your layout, you have to regenerate your error_request.cfm page. Of course, you could just not use any layout at all, but most people want their pages to have a standard look and feel.
Unfortunately, nothing is logged when this error happens. So what can you do? One thing to consider is checking the web server log files to see when the file is run. If you see it running often, then double check your error.cfm file for possible errors. If worse comes to worse, temporarily wrap your error.cfm itself in a try/catch and see what shows up when you dump cfcatch. I'm open to suggestions here - but there is a reason they (ok, I) call this the "Oh Crap" error.
Ok, so I've covered quite a bit of information here, but it applies to Application.cfm and CFERROR. What if you are using Application.cfc? Well one thing to remember is that you can just as easily put CFERROR tags inside your Application.cfc file. That is allowed, and I've done that before. But what if you want to use the onError method?
In general - a lot of what I said about the Exception type for CFERROR applies here. You want to present a nice message to your user. You want to log the error. You want to email the error to yourself. But there are some subtle differences.
Consider this very simple onError:
<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfdump var="#arguments#"><cfabort>
</cffunction>
All I've done here is dump all the arguments sent in. Now go back to your error file (the one you made to throw errors) and change it to this:
<h1>Hellow World</h1>
<cfoutput>#xfhdshsdhj#</cfoutput>
Run it in your browser, and you will see this:

Notice that the HTML before the error is displayed in the browser. If we had used a nice error message instead of the dump, the user would see both. This can result in oddly formatted pages. What you can do instead is simply handle the error and cflocate to the a nicer page:
<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfset var errortext = "">
<cflog file="myapperrorlog" text="#arguments.exception.message#">
<cfsavecontent variable="errortext">
<cfoutput>
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<cfdump var="#arguments.exception#" label="Error">
<cfdump var="#form#" label="Form">
<cfdump var="#url#" label="URL">
</cfoutput>
</cfsavecontent>
<cfmail to="bugs@myproject.com" from="root@myproject.com" subject="Error: #arguments.exception.message#" type="html">
#errortext#
</cfmail>
<cflocation url="error.cfm">
</cffunction>
All I did was take the code from my original error.cfm file and place it in here. The Exception argument here looks a bit different. No diagnostics key. So I just logged the message for now. My error.cfm file now only contains the message:
We are so sorry. Something went wrong. We are working on it now.
Lets recap:
- Do a quick test to figure out how your application responds to errors.
- If robust exeception information is displayed, turn it off.
- Use CFERROR or onError to handle errors.
- Do your own logging, and email yourself a detailed report.
I hope you find this guide useful, and please let me know how I can improve it.
Comments
...do these two dumps need to be prefaced with "StructKeyExists":
<cfdump var="#form#" label="Form">
<cfdump var="#url#" label="URL">
?
In which case you could use either methods shown above, those being a global error template in CF Admin or a 'request/oh crap' cferror in onRequestStart()
Nice post Ray
I've been using cfdump in the email that goes out when an error occurs as you illustrate in your Application.cfc code above.
One issue that has always bothered me (mainly because I'm AR) is the extra output in the email that cfdump causes. All the text for the javascript functions that control toggling just get dumped into the email's body. All I want to have in my email body are the contents of the structures (Exception, Form, Session, CGI, etc).
I've tried using cfloop with collection = but the problem is that some of the structures contain complex elements (arrays, another structure) as values so the cfloop collection = fails.
This cfdump issue actually caused me a problem with one of my email clients. That POP3 email client would not display the output from cfdump because with the extra javascript code text outputted the HTML for the email body was not well formed. So I got just part of the error message and no data from the structures.
So if anyone has a good replacement for cfdump to output the complete contents of the structures (Exception, Form, Session, CGI) in a manner that will display correctly in an HTML formatted email, I'd love to hear about it.
<cfdump var="#application#" format="text">
Specifically, format=.
<!--- outputs as text--->
<cfdump var="#cgi#" format="text">
vs
<!--- outputs as HTML --->
<cfdump var="#cgi#">
I posted a bug with Adobe.
The "format" attribute should be a killer way to get detailed errors on the mobile phone (at last!).
We do something similar on our production server and this is very useful to notify us errors in real time and to provide a better look & feel to error pages.
Great article, thanks. I wanted to print it but found no good way to do so. Do you have a printer-friendly feature that is not turned on? Would be awesome to be able to print these in a printer-friendly way.
k2
It looks like the format option is supposed to be used with the output attribute. That is when it defaults to text.
@Bruce
I imagine you could write a more complex error.cfm template and then just do a test on each collection item in your cfloop to determine its type and then handle the output appropriatly via the isSimpleValue(), isArray(), isStruct(), isXML() functions.
CoolJJ
Nice and helpful post. If i implement it on MX7 the whole mail is visible on the page and all cf code shows on view source?
what am i missing?
@Franz - so if you remember, I mentioned there were two types of errors. Exception=You can use CFML, Request=You Can't. Did you only use the Request one? Remember to use 2 different templates.
I use
<cferror type="exception" template="error.cfm">
<cferror type="request" template="error_request.html">
the x.cfm is online if you want to check. Look at the <cfset x = 1> in the page source.
Thanks franz
I changed it back. It shows only on my live but not on the development server. Witch cf server setting could cause it?
Thanks
K2
Try this out. :)
That's what i have. The first 2 lines of application.cfm are:
<cferror type="exception" template="error.cfm">
<cferror type="request" template="error_request.html">
How do I go about creating a Request or Validation error to test this.
Don't worry about validation errors. They are used when you use CF's built in form checking, which no one uses, and no one should use.
The function:
<code>
<cffunction name="onError" returntype="void" output="true">
<cfargument name="Exception" required="true">
<cfargument name="EventName" type="string" required="true">
<cferror type="request" template="error/RequestErrorDetail.cfm">
<cfinclude template="error/ErrorDetail.cfm">
</cffunction>
</code>
This does work, but I find it much more useful to error trap the exception error page this way.
<code>
<cffunction name="onError" returntype="void" output="true">
<cfargument name="Exception" required="true">
<cfargument name="EventName" type="string" required="true">
<cftry>
<cfinclude template="error/ErrorDetail.cfm">
<cfcatch type="any">
<cfdump var="cfcatch">
</cfcatch>
</cftry>
</cffunction>
</code>
This way I can email the request error (or any other error the 'error' page generates) using the cfcatch scope or do whatever I want with it. Is there a problem doing it this way?
I'm still a bit cloudy on how to incorporate handling your "oh, crap" error into the onError in Application.cfc. Do you have a quick version of the onError function that you can post to show how you handle both?
I have implemented the error handling code in my Application.cfc using the onError() method and all works fine except for the <cferror> tag in the onRequestStart() method to trap the request error.
I have included my Application.cfc for reference:
<cfcomponent output="false">
<cfset this.name = "mytestportal">
<cfset this.applicationTimeout = createTimeSpan(0,0,20,0)>
<cfset this.clientManagement = true>
<cfset this.clientStorage = "cookie">
<cfset this.loginStorage = "session">
<cfset this.sessionManagement = true>
<cfset this.sessionTimeout = createTimeSpan(0,0,20,0)>
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfreturn true>
</cffunction>
<cffunction name="onApplicationEnd" returnType="void" output="false">
<cfargument name="applicationScope" required="true">
</cffunction>
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cferror type="request" template="dspErrorRequest.cfm">
<cfreturn true>
</cffunction>
<cffunction name="onRequest" returnType="void">
<cfargument name="thePage" type="string" required="true">
<cfinclude template="#arguments.thePage#">
</cffunction>
<cffunction name="onRequestEnd" returnType="void" output="true">
<cfargument name="thePage" type="string" required="true">
</cffunction>
<cffunction name="onError" returnType="void" output="false">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfset var errortext = "" />
<cfset var mailToAddr = "developersEmail@developers.com" />
<cfset var mailFromAddr = "applicationEmail@appDomain.com" />
<!---
IF DEVELOPMENT, SIMPLY USE THIS...NO NEED TO SEND EMAILS!
<cfdump var="#arguments#"/><cfabort/>
--->
<cflog file="#this.name#" text="#ARGUMENTS.exception.message# - #ARGUMENTS.exception.RootCause.Message#" />
<!--- BUILD THE EMAIL CONTENT --->
<cfsavecontent variable="errorText">
<cfoutput>
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.que... />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<cfdump var="#ARGUMENTS.exception#" label="Error">
<cfdump var="#FORM#" label="FORM">
<cfdump var="#URL#" label="URL">
<cfdump var="#SESSION#" label="SESSION">
<cfdump var="#CGI#" label="CGI">
</cfoutput>
</cfsavecontent>
<!--- E-MAIL THE ERROR TO THE DEVELOPER(S) --->
<cfmail to="#mailToAddr#" from="#mailFromAddr#" subject="Error: #ARGUMENTS.exception.message#" type="html">
#errorText#
</cfmail>
<cflocation url="dspError.cfm">
</cffunction>
<cffunction name="onSessionStart" returnType="void" output="false">
</cffunction>
<cffunction name="onSessionEnd" returnType="void" output="false">
<cfargument name="sessionScope" type="struct" required="true">
<cfargument name="appScope" type="struct" required="false">
</cffunction>
</cfcomponent>
When I added an invalid CFML tag in my error handler page:
<cfpoo >
kjhgjhg
</cfpoo>
I simply get the standard coldfusion error message:
A tag starting with 'CF' has been detected. This tag is not supported by this version of ColdFusion. Please verify your typo and try again.
Is there something I'm doing wrong or can you confirm the exact method for trapping these coldfusion errors, if possible?
Thanks!
Thank you Ray.
See you at Sakura. :)
One thing that we have been doing is to clean up the error text into a simple readable email and log format by parsing the error structure, there is still an option to dump if the need is there (our error handler is a component that exists in the application layer and is called from the application.cfc). But normally you can get what you need through a little parsing which I find much easier to digest when coding.
Another thing that we do is check to make sure that things exist before we attempt to email them, for instance I have run into errors where parts of the session simply do not exist or even some of the application layer components, so I've learned to put a isdefined() check on almost anything that get's parsed. If it's not there then it's simply not provided, it's more work but in liue of a huge message it's very useful for us.
Thanks
-Paul-
Do you know of a way to access the (optional) errorcode and (custom) type cfthrow args from a (CFERROR) error handling page.
It looks like errorcode and type are only available within a cfcatch block and do not bubble up to the cferror page.
Cheers
David
On further investigation, I didn't look hard enough.
Within a CFCATCH the errorcode etc is available (top-level) within the cfcatch struct. Once passed to a cferror template the error object is no longer in the top-level of the error struct but available at error.RootCause.
What started to trick me is cfcatch.type will report a custom error type but error.type (even when a custom error is specified) will always be 'coldfusion.runtime.CfErrorWrapper'.
(I'm using CF8,0,0,176276 Enterprise)
Cheers
David
<cferror type="request" template="error_request.cfm"> to the onRequestStart() function in Application.cfc but it doesn't seem to catch the error and display the custom template. I still get the standard coldfusion error message. Any help would be greatly appreciated. Thanks!
Unfortunately we are still running CF7 and plan to do so for a few more months. What is your solution for missing template handling on CF7, cos the setting in CF Administrator simply does not work on boxes hosting more than one site!
Thanks,
Steve
I have implemented a solution for the complete exception and request error handling - just haven't got round to posting it.
If you don't mind - and Ray doesn't mind me using this post for this - you can mail me directly for the source code to n.odoherty [at] niallodoherty [dot] com
These are in no way complete - but were intended to be used as a starting point for implemnting in new applications. Therefore there will be "some" changes required.
Now, with the new servers we started to have severe performance issues and to top that some data loss also was happening. It appeared as if data was rolled back. Today, we turned off the error handling and the servers are working like a charm now.
Now, we are not entirely sure if the error handling caused all the problems because we were also trying other things like rebuilding indexes for database tables. Anyone had similar issues? Can cftry cause this kind of data rollbacks?
You do know that CF5 does support cferror, right? Why not just use that?
I love to have try/catch blocks on my error page as well, specifically early on.
There is not much worse than throwing an error on your error page while attempting to handle the email; logging for an error.
Dear user, while we were handling a system error another internal error occured, both have been noted
Quote from the MX7 LiveDocs: "To ensure that error pages display successfully, avoid using the CFENCODE utility to encode pages that include the CFERROR tag."
OK, I'm concerned about CFCOMPILE with deploy option, not the the old cfencode, and I'm specifying my CFERROR tags in Application.cfc, onRequestStart. Also integrating this with sitewide error management using onError and CFCATCH. So I'm really wondering if a sitewide error management strategy can be impacted by the use of compile. Thank you!
Also, just for clarification: Am I correct in thinking that CFTHROW or CFTHROW will stop execution in it's tracks and there would be no need for a CFABORT in that context? Example without a throw: CFCATCH output something CFABORT /CFCATCH... Of course we would want to use the abort to stop further execution, if that is desired.
Alternative Example: CFCATCH throw or rethrow right here /CFCATCH... In this alternative example, am I correct in thinking that the CFABORT would be unnecessary to halt execution past the CFCATCH, since the CFTRHOW or CFRETHROW would stop execution here and redirect to the error management routines?
Thank you for your post and advice.
I'm working on database conversions with several queries using ColdFusion.
I'm outputting the status of each group of queries when they begin and end. I have been hard coding the line numbers and would like to know if there is some CF variable that I can use to output the line numbers dynamically.
The problem is when I add code to the pages, the lines increase or decrease so the line numbers get screwed up.
I tried creating include files, but sometimes that's more work than it's worth.
Any ideas?
Thanks!
I have this at the top of the page:
<cfflush interval="10">
<cfset nowtime = #timeformat(now(),"hh:mm:ss")#>
Then I have the elapsed time calculated in an include file
Then the hard coded line number is output to the screen with the elapsed time so we know how long each query takes to run.
The line numbers are so we can easily find the queries in the file. If the page halts for server time outs or failures, we can quickly get to that location and examine it.
What is "GetFoo"?
getFoo was simply an example.
<cferror type="exception" template="errorException.cfm">
<cferror type="request" template="errorRequest.cfm">
in my application.cfm. On a basic error (like the one above), the page that gets called is the errorRequest.cfm and of course no cfml gets executed. Is there any setting in my server that would cause this?
Thanks!
Thanks!
ASP.NET would handle this without a blink.
CF handles this w/o a blink too. ;) Unless I'm misreading you somehow.
When logging or emailing the error I grab the relevant parts of the "error" structure.
On SQL errors I use error.RootCause.sql which reports the offending SQL. The problem is when using cfqueryparam the parameters are shown as (param 1)...(param X). How can I get the values of the parameters?
This is what I found in this regard: http://www.mail-archive.com/cfaussie@googlegroups.... but as you can notice is way too complicated.
Thank you
EstebanD
I have a customer who has an older system, meaning it was coded in CF4
He used a LOT of <INPUT TYPE="HIDDEN" NAME="FIELD_REQUIRED"
VALUE="YOU MUST SELECT A VALUE">
instead of using client side validation.
He came to me a few months ago wanting to upgrade to CF7.
I knew these among many other lazy coding techniques would bit me in the but, and i urged my customer to fix all this prior to the upgrade.
So know he has a site with 1500 documents that have 3000 some odd hidden fields that need to be replaced.
When i setup his App.cfc, i used some generic error catching and just shows an Opps page.
Problem is, those hidden required fields cause a CFTHROW which in turns stops processing and shows the Opps page.
I am now tasked with letting these errors slide through the onError() event. But how?
Is there a certain type of error this produces?
Anyway, thought I would add this to the comments about Error Handling. DONT USE HIDDEN REQUIRED FIELDS. they suck!!
Tim
turns out this will catch those errors in the onError() event
<cfif Arguments.Exception.message NEQ "Form entries incomplete or invalid.">
<cfoutput>#Arguments.Exception.detail#</cfoutput>
</cfif>
This still does not solve my issue. Seems like you could put a try on the form page to catch the error, wrong. its caught by App.cfc before it hits the form action page.
So ignoring this error seems impossible at this point.
Will update if I find a solution.
Tim
This should have EQ, not NEQ
<cfif Arguments.Exception.message EQ "Form entries incomplete or invalid.">
<cfoutput>#Arguments.Exception.detail#</cfoutput>
Fill out the form dummy :D
</cfif>
Thanks for yet another great article.
I'm using CF7 and whenever I try and log
#arguments.eventname# and #arguments.exception.message#
I get messages like this
"Error","jrpp-738","12/15/08","12:02:33","HRA_V2","Event Name: onRequest"
"Error","jrpp-738","12/15/08","12:02:33","HRA_V2","Message: Event Handler Exception."
I have found I need to look to the "Root Cause" to actually see the information you are mentioning:
<cflog file="#This.Name#" type="error" text="Template: #arguments.exception.RootCause.TagContext[1].template#">
<cflog file="#This.Name#" type="error" text="Line: #arguments.exception.RootCause.TagContext[1].line#">
<cflog file="#This.Name#" type="error" text="Message: #arguments.exception.RootCause.message#">
This produces:
"Error","jrpp-1603","12/19/08","09:18:21","HRA_V2","Template: /www/html/root/throw-error.cfm"
"Error","jrpp-1603","12/19/08","09:18:21","HRA_V2","Line: 1"
"Error","jrpp-1603","12/19/08","09:18:21","HRA_V2","Message: Variable XFHDSHSDHJ is undefined."
Curiously if I put <cfthrow object="#arguments.exception#"> in the onError function I see the real error (eg. Variable XFHDSHSDHJ is undefined), but if I <cfdump> it, it is wrapped in the "Event Handler Exception".
Any ideas? I'm confused as to why this happens to me but not anyone else? ;-)
Is there any problem with doing this:
arguments.exception.RootCause.TagContext[1].template
Will the exception passed into the onError() method of Application.cfc always have a RootCause, with a TagContext array of at least 1 element?
if structkeyexists(exception, "rootcause") and structkeyexists(exception.rootcause, "tagcontext") and arraylen(exception.rootcaue.tagcontext gte 1
<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfset var errortextemailonly = "">
<cfset var errortext = "">
<!--- plain error message email for IPhone --->
<cfsavecontent variable="errortextemailonly">
<cfoutput>
Error on Page: http://#cgi.server_name##cgi.script_name#/ param: #cgi.query_string#<br>
<br>
Refferal Page: #cgi.http_referer# <br>
<br>
User's IP: #cgi.REMOTE_ADDR#<br>
<br>
Server Port: #cgi.SERVER_PORT#<br>
<br>
Error Date: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br>
<br>
User's Browser: #cgi.HTTP_USER_AGENT#<br>
<br>
------------------------------------<br>
CF Error: #arguments.exception.message#<br>
</cfoutput>
</cfsavecontent>
<!--- full error message for desktop troubleshooting --->
<cfsavecontent variable="errortext">
<cfoutput>
#errortextemailonly#<br>
<cfdump var="#arguments.exception#" label="Error">
<cfdump var="#form#" label="Form">
<cfdump var="#url#" label="URL">
</cfoutput>
</cfsavecontent>
<cfif Application.emailErrorMessaging EQ "on">
<cfmail
to="dave@#Application.widgetURL#"
from="#Application.coname# <dave@#Application.widgetURL#>"
subject="Error #Application.coname# #arguments.exception.message#"
type="html"
server="#Application.mailServer#">
#errortextemailonly#
</cfmail>
</cfif>
<cfif #REMOTE_ADDR# NEQ #Application.davesIP#>
<!--- Show visitors the nicely formatted error --->
<cflocation url="exceptions/error_exception.cfm" addtoken="no">
<!--- Show me the full error for the desktop --->
<cfelse>
<cfoutput>#errortext#</cfoutput>
</cfif>
</cffunction>
We have on missing template handler in CF7 and CF8 and we can call in the Applicaiton.cfc file.But how can we handle the missing template error in CF earlier versions without setting up in ColdFusion administrator.
it will work in IIS as Ray points out, also in Apache as well, but you can forgot it if you want to do url rewrite with either of these webservers
the web server itself with do an internal redirect to the 404 page.
for plain error catching using a custom 404, it will work just fine.
The error handlers work, we get enough usage out of them to know that. There are times though that an error is not caught by our handlers, and gets caught by the site wide error handler.
My boss doesn't believe any error should ever make it that far, and all errors need to get caught and handled by our error handlers regardless of their cause. I believe he is being unrealistic about that, that there are some errors that just cannot be trapped beforehand and that is why the site wide error handler is there. But I need something to back up my thoughts.
I can give you a couple of examples of error messages the site wide has caught, if that is any help.
ERROR DIAGNOSTICS:String index out of range: -1 null <br>The error occurred on line -1. error.message = String index out of range: -1 error.rootCause = java.lang.StringIndexOutOfBoundsException: String index out of range: -1
ERROR DIAGNOSTICS:Session is invalid null <br>The error occurred on line 79. error.message = Session is invalid error.rootCause = java.lang.IllegalStateException: Session is invalid
ERROR DIAGNOSTICS:Operation failed on the data source named ""FREE"". Reason of failure ""java.sql.SQLException: [Macromedia][SQLServer JDBC Driver]Error establishing socket. Connection refused"" <br>The error occurred on line 96. error.message = Operation failed on the data source named ""FREE"". error.rootCause = coldfusion.runtime.ClientScopeDBException: Operation failed on the data source named ""FREE"".
I'm trying to be good and implement a catch-all error handling process using application.cfc. I should also mention that I'm using Fusebox 5.5 and have called the "Super" scope accordingly where needed.
I've tried several variations using this post and other examples but I just can't seem to get detailed info emailed to me while also redirecting the user to a "pretty" page. I'm also writing errors to a log file but so far that doesn't seem to be a problem.
Currently the <cflocation> tag in the onError method of app.cfc is causing it's own forever looping exception. I can instead <cfoutput> the "pretty" message directly from app.cfc but that can leave half drawn pages and other ugly results visible. I also tried GetPageContext() using cfscript but it has the same results as <cflocation>.
I've read about setting up a check to filter "coldfusion.runtime.AbortException" but if I've read correctly that is no longer needed since 7.01 (I'm on 7.02)... either way it has no effect.
My other issue is that the most common errors I'm testing for seem to miss the onError method completely. I can trap them by placing a <cferror type="request" template="Error.cfm"> in the OnRequestStart method, but then I'm limited to how I can format the error page and I can't email the error to myself (as pointed out above). I may just have to accept that but it's worth asking if there might be a better alternative... especially since it seems this may catch more than onError. Would a Try/Catch in OnRequestStart give me more options... or just shoot me in the foot?
Any ideas, clarifications or updates would be very much appreciated.
Anyway, I had the cflocation inside the onError method as in your example. To test, I was forcing an exception and seeing the exception error looping in my log file. I now find that the loop has nothing to do with exceptions. It's tied to cflocation.
I took out all of the onError stuff I was trying and then added some <cflog> tags to the methods in application.cfc. Then I just added a cflocation to one of my pages. It still loops but doesn't hit onError. I can see where new requests and sessions are being generated several times per second but never finishing. Fusebox is also reinitialized as part of the loop.
I have two identical files that I've tried to cflocate to. They are very basic and identical except one is named error.cfm and the other is error.htm. You are right that the htm file works just fine though I'm not sure what that tells me. Oh and I can also cflocate to an exernal url like "http://www.google.com" with no problem.
I suspect I'm just missing something in relation to launching fusebox 5.5 using application.cfc while also trying to do some other creative things with application.cfc. But hey, that's how we learn. If I never broke anything I wouldn't know how to fix anything.
I've developed a solution that stores errors as JSON data in a database. I only store the most recent 100 errors so that if a major glitch happens while I'm asleep it won't clog the database. When an error occurs, I send an email that only contains a basic message with the template and line number, and a link to my "error admin" which displays the verbose error data (that I stored as JSON) using cfdump.
Storing errors in a database lets me flag things that are fixed and things that are not using my "error admin", which is quite handy when I am procrastinating.
http://infosavvygroup.com/bugreport_request.cfm
Anyone notice that when the request error runs (and possibly the other errors too) it puts the error message into the http response header? Is there any way to hide it there so all it shows is a generic 500 error instead of mentioning whatever is going wrong in my code?
...Speaking of "never too much paranoia", didn't Adobe recently give an update to get ColdFusion to read .htm files like .cfm files? Talk about catering to the paranoid. :D
Are you saying you have an error handler, it says something simple "Oops", and yet you can still sniff out the underlying error? (ie, db, bad variable, etc)
I never got around to defining a mail server on my development server, mostly due to procrastination. So when I created "test.cfm" the error.cfm threw an error because of the cfmail tag which then led to the error_request.cfm. When I then checked the HTTP header on the error_request.cfm I got this: "500 No SMTP server specified for the cfmail tag."
Perhaps it's because it's an error caused by my failure to setup the SMTP server or because it's the error_request template. Maybe?
500 Internal Server Error
Nice and vague.
I have spoiled my one day to practice the Coldfusion Validations and I couldnt pass this guy. validateAt is not working for 'onsubmit' or 'blur', working perfectly for 'onserver'.
here is my code
----------------
<html>
<head></head>
<body>
<cfform action="insert2.cfm" method="post">
Enter a Number:
<cfinput type="text" name="ValNumber" maxlength="3" required="yes" validate="integer" validateat="onsubmit">
<cfinput type="submit" name="submit" value="submit">
</cfform>
</body>
</html>
Any help is highly appreciated, thanks
Jems.
[Application.cfc]
<cffunction name="onError">
<cfargument name="Exception" required=true/>
<cfargument type="String" name="EventName" required=true/>
<cfif NOT (Arguments.EventName IS "onSessionEnd") OR (Arguments.EventName IS "onApplicationEnd")>
<cfinclude template="includes/dsp_allErrors.cfm">
</cfif>
</cffunction>
[dsp_allErrors.cfm]
<cfsavecontent variable="theError"> #arguments.exception.message#
#arguments.exception.detail#
#arguments.exception.tagContext[1].template# LINE #arguments.exception.tagContext[1].line# <cfif ISDEFINED("arguments.exception.sql")>
#arguments.exception.sql#
</cfif>
</cfsavecontent>
<cflog file="AppErrorLog" type="error" text="#theError#">
I just pull the info out that I need instead of doing a full dump. How many acutally use the stack dumps etc? I haven't used a stack dump since my machine language days (which is back when we had to slide beads around on a framework)
Of course the user only sees "YOU BROKE IT YOU MORON!" message and I get the email telling me to check the log.

Thanks so much for taking the time to post this. I have been looking for something exactly like this for a while now, and it has helped to provide a context for attacking the error-handling issue that is still daunting for a relatively new CF developer such as myself.
Thanks for all that you do!