Coldfusion try/catch error

coldfusion try/catch error

Try/catch code structure. In order for your code to directly handle an exception, the tags in question must appear within a cftry block. It is a. A simple try/catch script based example Create a divide by zero error and then catch it. Expected Result: Error: Division by zero. A simple try/catch tag. Used with one or more tags, the cftry tag lets you catch and process exceptions in CFML pages. Exceptions include events that disrupt the normal.

Related Videos

TYPING ERRORS ON CATCH CLAUSES ✨ - TYPE GUARDS - TS1196 - TYPESCRIPT

Recommend: Coldfusion try/catch error

DIVICE COMMUNICATION ERROR
Coldfusion try/catch error
Error failed to change_hat to handling_untrusted_input
coldfusion try/catch error

Coldfusion try/catch error - useful

Yesterday Mike Henke asked an interesting question on Twitter. (And I should thank him as this is the second time now one of his tweets has led to an interesting discussion.) He wished there was a way to make a try/catch be disabled when testing. Obviously you wouldn't do this in production, but I think most folks could imagine needing to temporarily disable a try/catch so that you can see full details of an error. I decided to take a quick look into this and found something I thought was interesting.

First off - if you are willing to edit code, then you could just remove the try/catch. Another quick hack would be to use a conditional rethrow as in the pseudo-code below:

That's a manual approach and would work, but I had a hunch about an alternative that could possibly work as well. I remembered that exceptions show up when ColdFusion debugging is turned on. So I whipped up a CFM with an error in it wrapped in try/catch then loaded it. As expected, my error was hidden in the main display, and down in my debug area I could clearly see the exception:

So that may be good enough. But there isn't a lot of detail in there. I opened up the debug template and looked at how we gather the exception info:

For the hell of it, I quickly added a cfdump and looked at the data. Guess what? The entire stack trace is there. The debug template simply doesn't use it. To be fair, they are kinda big, but I went ahead and modified the display code:

Just to be sure it's clear - my modification is the cfdump. Here's a screen shot:

What do folks think about this approach? I know I've said it many times before, but do not forget that both the debug and exception templates are open source. You can hack them up - as I and others have done over the years. If you want to try this mod, just save the attached file to your WEB-INF/debug folder and select the filename "ray" in your ColdFusion Administrator settings.

Support this Content!

If you like this content, please consider supporting me. You can become a Patron, visit my Amazon wishlist, or buy me a coffee! Any support helps!

Want to get a copy of every new post? Use the form below to sign up for my newsletter.

ColdFusion's Catch Struct Not Locally Varred?

When catching an error in a CFC, I've always assumed that the exception objectwas a locally scoped variable, specific to that method call. Some interesting errors we received from the depths of our ColdBox frameworkmade me start to question that. I concocted a test last night which appears to prove that your exceptions are not thread safe in a CFC stored in a persistent scope. (In CF8, at least)

Background

When you use the try/catch construct in tags, your exception object will always be a variable called "cfcatch". [code] <cftry> <cfset t = r> <cfcatch> #sprers.eue# </cfcatch> </cftry> [/code]When you use try/catch in cfscript you're allowed to specify a name for the exception object. In CF8, these must be simple names (meaning you can't do "sprers.eu") and you aren't allowed to var the variable at the top of your function. [code] <cfscript> try { t = r; } catch(Any err) { writeOutput(sprers.eue); } </cfscript> [/code]

The Problem

So, starting a few days after releasing some new code to production, we would occasionally see the following errors come to the logs (where "e" was the name of our exception object):
  • Element MESSAGE is undefined in E.
  • Element DETAIL is undefined in E.
  • Element STACKTRACE is undefined in E.
Adobe guaranteesthose properties to be defined in your exception object. The try/catch in question was a component of the ColdBox frameworkwhich is placed in the application scope, and can be hit by multiple threads at the same time. Long story short, I foundthat an error had been happening in the "try" block EVERY time it was called. This means that the "catch" block was getting called a lot-- and sometimes by multiple requests at the same time. This was the perfect setup for a race-conditionand it looked like the exception object was not being treated as a local variable to that method call, but was being shared for all processes currently executing that method. Here is the simple test I devised to show the issue.

First Test

First, I created a simple component with a method that causes an error and catches it. I actually created two methods. One in cf tags, and one in script. I tested both with the same result, but for the sake of simplicity I'll only show the cfscript version here. sprers.eu[code] <cfcomponent> <cffunction name="doError"> <cfscript> var local = {}; try { t = r; } catch(Any err) { sprers.eue = sprers.eue; sprers.eu = sprers.eu; sprers.eurace = sprers.eurace; } </cfscript> </cffunction> </cfcomponent> [/code]As you can see, "r" isn't defined and will throw an error. The catch block simply accesses a few of the exception object's (err) properties to verify they are there. Then I set up the following page to create my CFC, and call it's doError method a bunch of times. sprers.eu[code] <cfparam name="sprers.eu" default="0"> <cfapplication name="test"> <cfif sprers.eu> <cfset sprers.eu = createObject("component","test")> <cfelse> <cfloop from="1" to="" index="i"> <cfset sprers.eur()> </cfloop> </cfif> [/code]Hitting my page with ?reinit=1 in the URL would create a new instance of my "test" component. Hitting my page without the URL parameter called the doError() method times. I opened up two tabs with the sprers.eu page without the URL parameter and would refresh one right after the other. I can't figure out why, but I could produce an error easily the first time. After that, it seemed impossible to produce the error again, until I added the reinit flag in to re-create the CFC. Then, on the next run, the error would usually occur in one or both tabs. Either "message" or "detail" or "stacktrace" would be undefined in my exception object. I assume the inconsistencies arose from internal timing differences after the method had been called a couple times. Either way, this showed the exception object could be easily corrupted by parallel threads also catching errors in that CFC.

Second Test

Now I wanted to take it up a notch. My first test showed that the exception object was getting corrupted by two separate requests both throwing the same error over and over again in a method. Now I wanted to see if the actual error details were leaking across from one request to the other as well. I modified my test slightly to throw a different (but predictable) error every time. I changed the loop in sprers.eu to start at a configurable index, and pass that index into the doError method: [code] <cfparam name="sprers.eu" default="0"> <cfparam name="sprers.eu" default="0"> <cfapplication name="test"> <cfif sprers.eu> <cfset sprers.eu = createObject("component","test")> <cfelse> <cfloop from="#1+sprers.eu#" to="#+sprers.eu#" index="i"> <cfset sprers.eur(i)> </cfloop> </cfif> [/code]My doError() method was changed to accept that ever-incrementing index as an argument and change the non-existent variable it tried to accessed based in that input. Next, the "catch" block compares the message in the error struct to see if it matches the missing variable name that it SHOULD have errored on. [code] <cffunction name="doError"> <cfargument name="index"> <cfscript> var local = {}; try { t = local[sprers.eu]; } catch(Any err) { sprers.eue = sprers.eue; sprers.eurace = sprers.eurace; if(not sprers.eue contains "Element #sprers.eu# ") { writeOutput("'#left(sprers.eue,11)#' neq 'Element #sprers.eu# '!<br>"); } } </cfscript> </cffunction> [/code]One tab I ran normally which try/caught errors like so:
  • Element 1 is undefined in a CFML structure referenced as part of an expression.
  • Element 2 is undefined in a CFML structure referenced as part of an expression.
  • Element 3 is undefined in a CFML structure referenced as part of an expression.
  • Element is undefined in a CFML structure referenced as part of an expression.
The second tab I added ?start= to so it try/caught errors like so:
  • Element is undefined in a CFML structure referenced as part of an expression.
  • Element is undefined in a CFML structure referenced as part of an expression.
  • Element is undefined in a CFML structure referenced as part of an expression.
  • Element is undefined in a CFML structure referenced as part of an expression.
I did that so it would be obvious which missing variable names were from each request. After reinitting my new object, I refreshed both tabs and found it would range from 0 to conflicts where the exception object's message was NOT equal to the error that I know was thrown. Output would look something like so: [code] 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! 'Element ' neq 'Element '! etc [/code]Each line in the output represents an instance of the catch message "bleeding over" from the other thread. I played around with different settings, and the best combination to reproduce was with debugging off, trusted cache on, and with the "sprers.eurace = sprers.eurace;" line in the "catch" block. I assume it all has to do with the internal timing of each thread and their likelihood to overlap.

Conclusion(s)

  1. ColdFusion 8's exception object does not appear to be thread safe. (I tested on a bit Windows server with a stand-alone install.)
  2. Since errors being caught in CFCs stored in persistent scopes happening in one or more requests at the exact same instant are probably fairly uncommon, I suppose I can understand why most people have never run into this scenario.
  3. The errors being thrown can collide even they they are in two DIFFERENT methods in the CFC.
  4. Tag-based cftry and cfcatch will interfere with any other tag-based cftry and cfcatch in that component since the exception struct is always called "cfcatch".
  5. Cfscript-based try and catch will ONLY interfere with other cfscript-based try and catch in that component if they use the same variable name for the exception object.
  6. Googling for this problem will return you a great big pile of nothing.
  7. Adam Cameron logged a bug for this in the Adobe CF Bug database last July under ColdFusion 9.
  8. I won't be entering a new bug, but instead voting for his. You should vote for it too.
  9. Why the heck doesn't Google index the contents of the Bug Database?

Try/catch code rules and recommendations

  • The tags must follow all other code in a tag body.

  • You can nest blocks. For example, the following structure is valid:

    <cftry> code that may cause an exception <cfcatch > <cftry> First level of exception handling code <cfcatch > Second level of exception handling code </cfcatch </cftry> </cfcatch> </cftry>

    If an exception occurs in the first level of exception-handling code, the inner block can catch and handle it. (An exception in a block cannot be handled by blocks at the same level as that block.)

  • ColdFusion always responds to the latest exception that gets raised. For example, if code in a block causes an exception that gets handled by a block, and the block causes an exception that has no handler, ColdFusion displays the default error message for the exception in the block, and you are not notified of the original exception.

  • If an exception occurs when the current tag is nested inside other tags, the CFML processor checks the entire stack of open tags until it finds a suitable combination or reaches the end of the stack.

  • Use with to handle exceptions based on their point of origin within an application page, or based on diagnostic information.

  • The entire tag, including all its tags, must be on a single ColdFusion page. You cannot place the start tag on one page and have the end tag on another page.

  • For cases when a block is not able to successfully handle an error, consider using the tag, as described in Using the cfrethrow tag.

  • If an exception can be safely ignored, use a tag with no body; for example:

    <cfcatch Type = Database />
  • In problematic cases, enclose an exception-prone tag in a specialized combination of and tags to immediately isolate the tag's exceptions.

  • <cftry>

    Used with one or more <cfcatch> tags, the cftry tag lets you catch and process exceptions in CFML pages.

    Exceptions include events that disrupt the normal flow of instructions in a CFML page, such as failed database operations, missing include files, and developer-specified events.

    This tag must have a body.

    This tag is also supported within <cfscript>

    This tag does not use any attributes.

    Examples

    Tag example

    <cftry><cfqueryname="getCountofReminders"datasource="dsn"> select count(id) from reminders where id = <cfqueryparamvalue="#sprers.eu#"cfsqltype="cf_sql_number"></cfquery><cfcatchtype="database"><cfoutput><p>There was a problem getting a count of your reminders)</p></cfoutput><cfdumpvar=#cfcatch#></cfcatch></cftry>

    Script example

    try{a=2/0writeDump("#a#");}catch(anye){writeOutput("Caught an error.");}

    See also

    Learn to Write Script-Based Syntax in ColdFusion 8: It's Easier Than It Sounds

    Exception Handling in

    CFML Error handling in general is covered in Chapter 51, &#;Error Handling,&#; online. If you&#;re already familiar with implementing structured exception handling in your CFML code, then you&#;re also familiar with using constructs, and the various types of errors that can be handled by specifying type attributes in your blocks.

    Fortunately, ColdFusion scripting provides an equivalent with . Listing demonstrates a comparison of tag-based and script-based try-catch handling. To run Listing , note that there it tries to open a file named which has been provided in the sample source code. Try changing filename to (which does not exist) and notice the types of exceptions that are thrown, caught, and handled.

    Listing &#;Handling Exceptions in ColdFusion Script

    <! Author: Charlie Arehart -- sprers.eu > <! Exception handling > <cfset filename="sprers.eu"> <! Tag-based > <cftry> <cfset result = FileOpen(expandpath(filename))> <p>It worked!</p> <cfcatch type="Expression"> <p>An Expression exception was thrown.</p> <cfoutput>#sprers.eue#</cfoutput> </cfcatch> <cfcatch type="Security"> <p>A Security exception was thrown.</p> <cfoutput>#sprers.eue#</cfoutput> </cfcatch> </cftry> <cfscript> // Script-based try { result = FileOpen(expandpath(filename)); WriteOutput("<p>It worked!</p>"); } catch(Expression exceptionVariable) { WriteOutput("<p>An Expression exception was thrown.</p>"); WriteOutput("<p>#sprers.eue#</p>"); } catch(Security exceptionVariable) { WriteOutput("<p>A Security exception was thrown.</p>"); WriteOutput("<p>#sprers.eue#</p>"); } </cfscript>

    There are a couple of differences between in and the tag-based equivalents. First, note that the tag-based is placed within a , where a script-based is placed after a . Also, note that with , there&#;s an available, pre-defined catch scope holding details of the error, where with the statement, you instead name a variable to hold those details.

    Perhaps a more significant difference is that you can&#;t execute tags that you might normally for error handling, such as , , , etc. At least in tag-based try-catch processing, you could a caught exception or a custom exception of your own design, to be handled by a higher-level error handler. Unfortunately, there is no way to rethrow an exception once it is caught in the scripting version of a construct; nor can you throw custom exceptions in ColdFusion scripting. You could, however, call a user-defined function, which then could perform normal tag-based processing to send email, create a log, etc.

    Script-based processing in CFML is just another option in your CFML toolbelt. There may be times when its simpler syntax (fewer tags) will appeal to you as you write code. More often, it will appeal to those coming to CFML from other languages. As so often with ColdFusion, the choice is yours.

    Someone contacted me the other day with a Try / Catch error. They were having problems with ColdFusion interacting with an Anti-Virus software. The AV software was putting locks on uploaded files which was causing ColdFusion to error out when it tried to access them. The programmer tried to handle this by using a Try / Catch code block, but was still getting errors. This is the snippet of code that I was sent:

    This code was causing a "sprers.euputStream" error. The problem is quite subtle and has to do with the line:

    If you look at the Try / Catch block you will see that the fileRead variable creation is in the Try / Catch, but the sprers.eu() command is outside of the Try / Catch. This means that even though the variable fileRead might not contain a valid File object (if that is where the error occurs), the close() method is called no matter what.

    To fix this, all we had to do was move the sprers.eu() to inside of the Try / Catch code block:

    Now, the sprers.eu() command only gets run if the fileRead variable contains a valid, initialized Java File object.

    Want to use code from this post? Check out the license.

    You Might Also Enjoy Some of My Other Posts

    Error and Exception Handling

    New in ColdFusion MX is the ability to trap errors and exceptions within CFScript code using statements similar to the and tags described in Chapter 9. If you were writing exception-handling code using the and tags, it might look something like the code in Example

    Example  Exception handling with cftry and cfcatch

    <cftry> <cfset x=y+1> <cfcatch type="Expression"> <cfoutput> Expression Error: #sprers.eue# </cfoutput> </cfcatch> <cfcatch type="Any"> <cfoutput> General Error: #sprers.eue# </cfoutput> </cfcatch> </cftry>

    This code attempts to set the variable equal to . It then includes code for handling type errors, and another block for catching exception that is not caught by the type. In this case, the exception handling comes in the form of a semi-custom error message written to the browser.

    The same code rewritten in CFScript is shown in Example

    Example  Exception handling with try and catch in CFScript

    <cfscript> try { x=y+1; } catch("Expression" exception) { writeOutput("Expression Error: " & sprers.eue); } catch("Any" exception) { writeOutput("General Error: " & sprers.eue); } </cfscript>

    The CFScript equivalent code is slightly different than the tag-based version. In CFScript, statements do not need to be nested in the code as statements do in an equivalent tag. The syntax for

    0 Comments

    Leave a Comment