DevLearningTools

MODULE 12 · LESSON 03

try / catch

The same exception handling as cftry/cfcatch, written in CFScript: try/catch/finally syntax, displaying exception details with dump/echo, and rethrowing or chaining an exception to its root cause.

New lessons are added one at a time as the course gets built out — a graded quiz for each lesson is still on the way.

The previous two lessons covered cftry and cfcatch in tag syntax. CFScript offers the exact same capability with try, catch, and finally statements, same behavior, same exception types and fields, just without the angle brackets.

Learning Objectives

After completing this lesson, you'll be able to:

  • Write the same exception handling in CFScript's try/catch/finally form.
  • Display a caught exception's details with dump or echo without stopping execution.
  • Rethrow an exception after logging it, or chain a new exception to the one that caused it.

The Same Structure, in CFScript

CFScript
try {
    result = 10 / arguments.divisor;
} catch (any e) {
    writeOutput("Something went wrong: " & e.message);
} finally {
    writeLog(text="Division attempt finished");
}
Tag Syntax — for comparison
<cftry>
    <cfset result = 10 / arguments.divisor>
    <cfcatch type="any">
        <cfoutput>Something went wrong: #cfcatch.message#</cfoutput>
    </cfcatch>
    <cffinally>
        <cflog text="Division attempt finished">
    </cffinally>
</cftry>
NOTE

In CFScript, catch and finally follow the try block as separate clauses, they are not nested inside it. Everything from the previous two lessons, the built-in exception types, the cfcatch object's fields, catch block ordering, applies identically here.

How finally Fits Into the Flow

try Block Runs

Exception? catch Handles It

finally Always Runs

Execution Continues

NOTE

finally runs whether or not an exception occurred, and whether or not the catch block itself succeeded, it's the one place guaranteed to execute for cleanup.

Displaying Exception Details Without Stopping Execution

CFScript
try {
    throw "Something specific went wrong";
} catch (any e) {
    dump(e);   // full structure, including the stack trace
    // or:
    echo(e);   // a simpler, shorter representation
}
NOTE

dump() shows the exception's full structure and stack trace. echo() prints a simpler representation. Neither one stops execution, the code after them keeps running.

Rethrowing and Chaining an Exception

CFScript — rethrow the original
try {
    riskyOperation();
} catch (any e) {
    writeLog(text="Logging before rethrow: " & e.message);
    rethrow;
}
CFScript — chain a new exception to the original (Lucee 6+)
try {
    processPayment();
} catch (any e) {
    throw(message="Payment batch failed", cause=e);
}
NOTE

rethrow (cfrethrow in tag syntax) re-raises the exact exception currently being caught, useful for logging before letting it propagate further. Lucee's cause parameter on throw instead wraps the original exception inside a new one, preserving it in the stack trace as the underlying cause.

Common Beginner Mistakes

Forgetting that CFScript's catch and finally sit outside the try block, not inside it

In CFScript syntax, catch and finally are separate clauses that follow the try block, unlike some other languages' formatting conventions might suggest.

Assuming finally only runs when there was no exception

finally always runs, whether the try block succeeded, failed, or the catch block itself threw a new exception.

Swallowing an exception silently instead of logging or rethrowing it

A catch block with no logging and no rethrow makes a real failure invisible. At minimum, log it before deciding not to propagate it further.

Best Practices

  • Use finally for cleanup that must always happen, closing a connection or file handle, regardless of success or failure.
  • Log the original exception (or chain it with cause) before rethrowing or wrapping it, don't let the original diagnostic detail get lost.
  • Prefer CFScript's try/catch/finally in CFScript-based code, and cftry/cfcatch/cffinally in tag-based files, for consistency with the surrounding code style.

Interview Questions

What's the difference between catch and finally?

catch handles a matching exception when one is thrown. finally runs regardless, whether or not an exception occurred, and is the one place guaranteed to execute for cleanup.

In CFScript, are catch and finally written inside the try block?

No, they're separate clauses that follow the try block, not nested inside it.

What does rethrow do, and why use it after logging?

It re-raises the exact exception currently being caught. It's commonly used to log or record an exception before letting it continue propagating up, rather than swallowing it silently.

What's the difference between dump(e) and echo(e) in a catch block?

dump() shows the exception's full structure and stack trace. echo() prints a simpler representation. Neither stops execution.

Summary

In this lesson, you wrote the same exception handling from the previous two lessons in CFScript's try/catch/finally form, displayed exception details with dump and echo without stopping execution, and rethrew or chained an exception to its root cause.

What's Next?

The next lesson covers throwing exceptions deliberately with throw/cfthrow, including custom types and attaching extended, structured error information.