I've washed more a few posts recently nigh fault handling and robust exception data, so I thought I'd write up one blog entry that tin can serve as a nice guide for folks to bookmark. By using "Complete" in the championship, I've also near 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 y'all how many errors your site threw yesterday, could you respond with 100% complete accuracy? I'd exist willing to bet most people would say no. Shoot, I know I couldn't respond that. So what do we practise 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 ane line into it:

                      <cfoutput>#xfhdshsdhj#</cfoutput>                  

The signal of this template is to create an error. Unless you actually have a variable defined with that ugly name, the template volition fault out. Upload information technology to your server and run information technology with your browser.

Ane of three things will happen:

  1. Y'all will get an fault with the full path shown, like below. This shows that you take non added error direction to your application, and that yous have Enabled Robust Exception information in your ColdFusion Ambassador. Finish reading this blog entry, become to your Admin, and disable it. Now. (Delight note that this guide is intended for a production machine environs. Obviously you can go along this setting on in evolution. I practice.)

  1. Y'all volition get an error with no path shown. This is slightly better. Information technology still shows that y'all haven't added error direction to your application though.

  1. Yous get an "error page". Past "error page" I mean a page maxim that an error occurred, merely displayed in your standard site layout, or close to it. That's good. Yous should yet proceed to read though as I'k going to discuss things that should ordinarily be in an error handler.

Ok, before going on - delete the page you just uploaded. I'd be willing to bet a practiced 40-50% of us upload exam.cfm type files to our servers and forget to delete them. I've never done that. Really.

And so - lets talk error treatment now. You accept 2 high level options. The offset is to set an error template in the ColdFusion administrator:

If you lot specify a template here, than ColdFusion will run the template when an error occurs. In general though I wouldn't recommend setting the template hither.

Your second pick - and what I recommend - is to the handle the errors specifically in your application. How? If y'all are on an older ColdFusion server and but have access to Application.cfm, then you want to the utilise the CFERROR tag. You can employ these tags in Application.cfc likewise, merely I recommend onError for that. I'm going to embrace both though.

A total description of cferror may be establish 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 mistake occurs. There are 3 main types of errors it monitors: Exception, Request, and Validation. Forget nearly validation. Don't use it. Exception is the type of error we are most familiar with. It is what I call the 'basic' error. Asking is the more serious error. It can occur when your error handler itself screws upwardly. I telephone call this the "Oh Southward***" error (seriously). Information technology has special restrictions on it I'll discuss in a 2nd. First though, let's wait at the syntax you would use in your Application.cfm file:

                      <cfapplication name="rayrules">  <cferror blazon="exception" template="error.cfm"> <cferror type="asking" template="error_request.cfm">                  

As you can meet - it's pretty simple stuff. I basically said - for the Exception (once more, think 'normal' error), run error.cfm. For the Oh Crap mistake, run error_request.cfm.

If you run whatever CFM again - you will immediately get an mistake stating that these files practice not exist. You should create blank ones for the time being.

Now for the details. The error.cfm template is a normal CFM page. Simply information technology has access to a special variable: ERROR. This variable is a structure that contains a lot of information almost 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'due south just do a quick dump.

                      <cfdump var="#mistake#">                  

If you run your mistake test over again (y'all may have to reupload information technology if you deleted it similar I suggested, but don't forget to remove it after!), you volition see something similar this:

I'g not going to list every field - again, check the cferror syntax doc for that. The item you lot volition most care near normal is cferror.message. This is the simplest representation of the error and will exist 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 desire your public site showing a dump. Let's brainstorm by outputting a nice message to the user. Here is the new version of mistake.cfm:

                      Nosotros are so sorry. Something went wrong. We are working on it now.                  

Obviously y'all tin can marking that upwards with overnice 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, merely we should practise something with the fault. I recommend two things.

Log the error. For some odd reason, ColdFusion volition 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, nosotros should:

                      <cflog file="myapperrorlog" text="#error.message# - #error.diagnostics#">                  

Note that I've specified the message and diagnostics variable. This is a scrap of a duplication since diagnostics information will have the same information every bit bulletin, but I similar the shortness of the message value. You could log more than this obviously, but since this is a log file, we don't desire to overdue it hither.

The next thing we should do is e-mail the error. This is something I've covered before on the blog, and then some of you may know my feelings on this already, simply what I typically exercise is e-mail me the entire mistake construction. I also include other structures so I can encounter 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(at present(), "short")#<br />  <cfdump var="#error#" label="Error"> <cfdump var="#form#" label="Form"> <cfdump var="#url#" characterization="URL">  </cfoutput> </cfsavecontent>   <cfmail to="bugs@myproject.com" from="root@myproject.com" subject="Error: #error.message#" type="html"> 	#errortext# </cfmail>                  

I create my message inside a cfsavecontent (more on why in a second), and then postal service information technology. Don't forget the type=html. Now as y'all tin can guess, this creates a pretty big email. If you lot get a 1000 of these, you will be suffering, just consider it incentive to ready the darn bug ASAP. Yous could also add together a dump of the session scope if yous wanted, or CGI. Basically, information technology is better to send more than data 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 mistake occurred.

And then why the cfsavecontent? One trick I'll often do is to skip the e-mail if I'm currently logged in every bit an admin on the site. I'll do a quick bank check, and if I'm an admin, I'll brandish the error on screen. This lets me encounter the error more quickly than waiting for an email.

So all together now, hither is the error.cfm file:

                      We are then sorry. Something went wrong. We are working on it now.  <cflog file="myapperrorlog" text="#fault.message# - #error.diagnostics#">  <cfsavecontent variable="errortext"> <cfoutput> An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br /> Time: #dateFormat(at present(), "short")# #timeFormat(at present(), "brusk")#<br />  <cfdump var="#fault#" label="Error"> <cfdump var="#class#" characterization="Course"> <cfdump var="#url#" characterization="URL">  </cfoutput> </cfsavecontent>   <cfmail to="bugs@myproject.com" from="root@myproject.com" subject="Fault: #fault.message#" type="html"> 	#errortext# </cfmail>                  

Now for fun, endeavour modifying your error.cfm. Change the first cfdump tag to a cfpoo tag. If you lot rerun your template, you will see a blank folio. Remember that nosotros created a blank error_request.cfm file earlier? This is what is running now. Basically, ColdFusion has noticed that we had an mistake, and then our mistake management had an error, and it's thrown it's easily up in the air and given up. Nosotros are now in the asking template. The asking template has special rules - the about important being - no CFML. That's right - you tin't cflog. You lot can't electronic mail the error. Yous tin can - however - output error variables. You don't use cfoutput, you just include them. Consider this sample:

                      This went incorrect: #error.diagnostics#                  

This will display:

This went wrong: Unknown tag: cfpoo. ColdFusion cannot make up one's mind 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 mistake occurred on line -1.

That's all you can do really. Merely approximate what - I wouldn't exercise that. Call back - we don't want to reveal whatsoever sensitive data to our users, including what caused an error. Then what practise I recommend?

Become to your site and view source. This will give you the HTML event of one of your pages. Notice the content and supersede information technology with a "We're sorry" type message like nosotros used in error.cfm. Then relieve that HTML. Basically you are creating a static page. This means that if you change your layout, y'all have to regenerate your error_request.cfm page. Of class, you could just not use any layout at all, but most people want their pages to take a standard look and feel.

Unfortunately, zero is logged when this mistake happens. Then what tin you do? I matter to consider is checking the web server log files to run into when the file is run. If yous see it running often, then double check your mistake.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 yous dump cfcatch. I'thousand open to suggestions here - but in that location is a reason they (ok, I) call this the "Oh Crap" error.

Ok, so I've covered quite a bit of information hither, but information technology applies to Application.cfm and CFERROR. What if you are using Application.cfc? Well one matter to remember is that you can but equally easily put CFERROR tags inside your Application.cfc file. That is allowed, and I've done that before. Simply what if you want to apply the onError method?

In general - a lot of what I said about the Exception type for CFERROR applies here. You want to present a overnice message to your user. You lot want to log the error. You want to electronic mail the mistake to yourself. Only there are some subtle differences.

Consider this very unproblematic onError:

                      <cffunction proper noun="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 hither is dump all the arguments sent in. Now go dorsum to your error file (the one you fabricated to throw errors) and change it to this:

                      <h1>Hellow World</h1> <cfoutput>#xfhdshsdhj#</cfoutput>                  

Run it in your browser, and you volition see this:

Discover 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 encounter both. This can effect in oddly formatted pages. What you lot can practice instead is simply handle the fault and cflocate to the a nicer folio:

                      <cffunction name="onError" returnType="void" output="true"> 	<cfargument proper noun="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="Fault"> 	<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 hither looks a chip different. No diagnostics central. So I but logged the message for now. My fault.cfm file now only contains the message:

                      We are so sorry. Something went wrong. We are working on it now.                  

Lets epitomize:

  • Practise a quick examination to figure out how your application responds to errors.
  • If robust exeception information is displayed, turn it off.
  • Employ CFERROR or onError to handle errors.
  • Do your own logging, and email yourself a detailed study.

I hope you find this guide useful, and delight let me know how I can improve it.