Handling Exceptions in ColdFusion

Ordinarily, when ColdFusion encounters an error, it stops processing and displays an error message or error page (as specified by the cferror tag). However, you can use ColdFusion's exception handling tags to catch and process exceptions in ColdFusion pages. Exceptions include any event that disrupts the normal flow of instructions in a ColdFusion page, such as failed database operations, missing include files, or developer-specified events.

In order for your code to handle an exception, the tags in question must appear within a cftry block. It is a good idea to enclose an entire application page in a cftry block. You then follow the cftry block with cfcatch blocks, which respond to potential errors. When an exception occurs within the cftry block, processing is thrown to the cfcatch block for that type of exception.


Note

For cases when the error handler is not able to successfully handle the thrown error, use the cfrethrow tag within a cfcatch block.


Here is an outline for using cftry and cfcatch to handle errors:

<cftry>

... Put your page's application code here ...

  <cfcatch type="exception type1">

  ... Add exception processing code here ...

  </cfcatch>

  <cfcatch type="exception type2">

  ... Add exception processing code here ...

  </cfcatch>

  <cfcatch type="Any">

  ... Add exception processing code appropriate for all other

      exceptions here ...

  </cfcatch>

</cftry>

To catch errors in a single problematic SQL statement, for example, you might narrow the focus by surrounding the ColdFusion tag that contains the SQL statement with a cftry block and following it with a cfcatch type="Database" tag that displays the information in the cfcatch.SQLState variable.


Note

Do not attempt to enclose an entire application in a cftry block by putting the cftry tag in Application.cfm because you cannot be sure that there always will be a matching cftry end tag.


For information on the cftry, cfcatch, cfrethrow, and cfthrow tags, see the CFML Reference.

Types of recoverable exceptions supported

ColdFusion Server supports several types of recoverable exceptions. Use the type attribute in the cfcatch tag to determine which type of exception to catch. You can also use these types as the values of the exception attribute in cferror type=exception tags.

You can specify the following basic exception types. For a list of advanced exception types, see the CFML Reference.
Type
Tag(s)
Notes
Database failures

cfcatch type="Database" 

Catch failed database operations, such as failed SQL statements, ODBC problems, and so on.
Template errors

cfcatch type="Template" 

Catch general application page errors.
The cfinclude, cfmodule, and cferror tags can generate a template exception.
Missing included file errors

cfcatch type="missingInclude" 

Catch errors where included files are missing.
Object exceptions

cfcatch type="Object" 

Catch exceptions in ColdFusion code that works with objects.
Security exceptions

cfcatch type="Security" 

Raise catchable exceptions in ColdFusion code that works with security.
Expression exceptions

cfcatch type="Expression" 

Catch exceptions when an expression fails evaluation.
Locking exceptions

cfcatch type="Lock" 

Catch failed locking operations, such as when a cflock critical section times out or fails at runtime.
Application-defined exception events raised by cfthrow

cfcatch type="Application" 

 

a cfcatch block that has no type attribute 

Catch only those custom exceptions that are specified as having the Application type in the cfthrow tag that defines them.
Custom exceptions raised by cfthrow

cfcatch

  type="custom_exception_type" 

Catch a custom a exception type raised by cfthrow.
Unspecified exceptions

cfcatch type="Any" 

Catch any exceptions that are not specifically handled in another error handler, including unexpected internal errors.

Specifying the type as any causes the ColdFusion Application Server to catch internal exceptions, memory allocation errors, and access violations, which you might not be prepared to handle.

Applications can optionally use the cfthrow tag to raise custom exceptions. Such exceptions are caught with any of the following type specifications:

The custom_exception_type type designates the name of a user-defined type specified in the cfthrow tag.

An exception raised within a cfcatch block cannot be handled by the cftry block that immediately encloses the cfcatch tag.

Exception information in cfcatch

Within a cfcatch block, the active exception's properties can be accessed as variables. The following variables are available in most cfcatch blocks:
Property variable
Description

cfcatch.type  

The exception's type, returned as a string.

cfcatch.message 

The exception's diagnostic message, if one was provided. If no diagnostic message is available, this is an empty string.

cfcatch.detail 

A detailed message from the CFML interpreter. This message, which contains HTML formatting, can help to determine which tag threw the exception.

cfcatch.extendedInfo 

A custom error message. This is returned only for cfcatch tags where type="Application" or a custom type.

cfcatch.errorCode 

Any exception that is a part of the CFML exception hierarchy supplies a value for this variable.
For type="Application", cfthrow tags can supply a value for this code via the errorcode attribute. For Type="Database", cfcatch.errorcode has the same value as cfcatch.sqlstate. Otherwise, the value of cfcatch.errorCode is the empty string.

cfcatch.tagContext 

Provides the name and position of each tag in the tag stack and the full pathnames of the files that contain the tags in the tag stack.

Tag context information

On the Debugging Settings page in the ColdFusion Administrator you can select the Enable CFML stack trace option. When you enable this option, cfcatch blocks make available an array of structures called cfcatch.tagContext. Each structure represents one level of the ColdFusion runtime's active tag context at the time when the ColdFusion interpreter detected the exception.

The structure at position 1 of the array represents the outermost tag in the stack of tags that were executing when the interpreter detected the exception. The structure at position ArrayLen(cfcatch.tagContext) represents the currently executing tag at the time the interpreter detected the exception.

The tagContext structures have the following attributes:


Note

Clear the Enable CFML stack trace option to avoid having production servers expend resources creating a traceback stack by default. When you turn off this setting, cfcatch.tagContext is a zero-length array.


Database exceptions

The following additional variables are available whenever the exception type is database:
Property variable
Description

cfcatch.nativeErrorCode 

The native error code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. The values assumed by cfcatch.NativeErrorCode are driver-dependent.
If no error code is provided, the value of nativeErrorCode is -1.

cfcatch.SQLState 

The SQLState code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. The values assumed by cfcatch.SQLState are driver-dependent.
If no SQLState value was provided, the value of SQLState is -1.

Expression exceptions

Property variable
Description

cfcatch.errnumber 

An internal expression error number, valid only when type="Expression".
The following variable is only available for expression exceptions:

Locking exceptions

The following additional information is available for exceptions related to cflock sections:
Property variable
Description

cfcatch.lockName 

The name of the affected lock. This is set to "anonymous" if the lock name is unknown.

cfcatch.lockOperation 

The operation that failed. This is set to "unknown" if the failed operation is unknown.

Missing include exceptions

The following additional variable is available if the error is caused by a missing file specified by a cfinclude tag:
Property variable
Description

cfcatch.missingFileName 

The name of the missing file.

Exception handling strategies

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

Use the cftry tag with one or more cfcatch blocks to define a ColdFusion block for exception handling. When an application page raises an error condition, the ColdFusion Server checks the stack of currently active blocks for a corresponding cfcatch handler. In particularly problematic cases, you might enclose an exception-prone tag in a specialized combination of cftry and cfcatch to immediately isolate the tag's exceptions, or to use cftry with cfcatch type="Any" at a main processing level to gracefully terminate a subsystem's processing in case of an unexpected error.

Exception handling example

The following example shows cftry and cfcatch, using the CompanyInfo data source used in many of the examples in this book and a sample included file, includeme.cfm.

If an exception occurs during the cfquery statement's execution, the application page flow switches to the cfcatch type="Database" exception handler. It then resumes with the next statement after the cftry block, once the cfcatch type="Database" handler completes.

Similarly, the cfcatch type="MissingInclude" block handles exceptions raised by the cfinclude tag. Any unknown, but possibly recoverable, exceptions are handled by the cfcatch type="Any" block.

<!--- Wrap code you want to check in a cftry block --->

<cfset EmpID=3>

<cftry>

  <cfquery name="test" datasource="CompanyInfo">

    SELECT Dept_ID, FirstName, LastName

    FROM Employee

    WHERE Emp_ID=#EmpID#

  </cfquery>



  <html>

  <head>

    <title>Test cftry/cfcatch</title>

  </head>



  <body>

  <hr>

  <cfinclude template="includeme.cfm">

  <cfoutput query="test">

  <p>Department: #Dept_ID#<br>

  Last Name: #LastName#<br>

  First Name: #FirstName#</p>

  </cfoutput>



  <hr>



<!--- Use cfcatch to test for missing included files. --->

<!---   Print Message and Detail error messages. --->

<!--- Block executes only if a MissingInclude exception is thrown. --->



  <cfcatch type="MissingInclude">

    <h1>Missing Include File</h1>

    <cfoutput>

    <ul>

      <li><b>Message:</b> #cfcatch.Message#

      <li><b>Detail:</b> #cfcatch.Detail#

      <li><b>File name:</b> #cfcatch.MissingFilename#

    </ul>

    </cfoutput>

  </cfcatch>



<!--- Use cfcatch to test for database errors.--->

<!---   Print error messages. --->

<!--- Block executes only if a Database exception is thrown. --->



  <cfcatch type="Database">

    <h1>Database Error</h1>

    <cfoutput>

    <ul>

      <li><b>Message:</b> #cfcatch.Message#

      <li><b>Native error code:</b> #cfcatch.NativeErrorCode#

      <li><b>SQLState:</b> #cfcatch.SQLState#

      <li><b>Detail:</b> #cfcatch.Detail#

      </ul>

    </cfoutput>

  </cfcatch>



<!--- Use cfcatch with TYPE="Any" --->

<!--- to find unexpected exceptions. --->



<cfcatch type="Any">

  <cfoutput>

    <h1>Other Error: #cfcatch.Type#</h1>

    <ul>

      <li><b>Message:</b> #cfcatch.message#

      <li><b>Detail:</b> #cfcatch.Detail#

    </ul>

    </cfoutput>

  </cfcatch>

</cftry>

  </body>

  </html>

To test the code:

  1. Make sure there is no includeme.cfm file and display the page. The cfcatch type="MissingInclude" block displays the error.
  2. Create a non-empty includeme.cfm file and display the page. If your database is configured properly you should see an employee entry and not get any error.
  3. In the cfquery tag change the line:
    FROM Employee
    
    

    to:

    FROM Employer
    
    

    Display the page. This time the cfcatch type="Database" block displays an error message.

  4. Correct Employer back to Employee. Change the cfoutput line:
    <p>Department: #Dept_ID#<br>
    
    

    to:

    <p>Department: #DepartmentID#<br>
    
    

    Display the page. This time the cfcatch type="Any" block displays an error message indicating an expression error.

Custom Exception Types

The type attribute allows a cfthrow tag to throw an exception of a specific type, which can be caught by a cfcatch tag that has a matching type attribute.

A cfthrow tag without a type attribute will throw a type="Application" exception.

Naming conventions

A naming convention for custom exception types follows a convention that is similar to Java class naming conventions: domain name in reverse order, followed by project identifiers, as in this example:

<cfthrow

  type="Invalid_field.codeValue"

  errorcode="Dodge14B">

The predefined exception types, except for type="Application", are reserved; for example, <cfthrow type="Database"> will be rejected.

A cfcatch tag can specify a custom type as well as one of the predefined types. For example, to catch the exception thrown above, you use this syntax:

<cfcatch type="Invalid_field.codeValue">

ColdFusion uses the catch type as a pattern to find a catch handler. For example,

<cfthrow type="MyApp.BusinessRuleException.InvalidAccount">

would be handled by any of the following cfcatch error handlers.

<cfcatch type="MyApp.BusinessRuleException.InvalidAccount">

<cfcatch type="MyApp.BusinessRuleException">

<cfcatch type="MyApp">

The handler that matches most exactly handles the error. Therefore, in this case, the MyApp.BusinessRuleException.InvalidAccount handler gets invoked. However, if you used the following cfthrow tag:

<cfthrow type="MyApp.BusinessRuleException.InvalidVendorCode

the MyApp.BusinessRuleException handler receives the error.

The type comparison is case-insensitive. To match types exactly, rather than performing pattern matching, use the cfsetting attribute catchExceptionsByPattern="No".



Banner.Novgorod.Ru