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
try {
result = 10 / arguments.divisor;
} catch (any e) {
writeOutput("Something went wrong: " & e.message);
} finally {
writeLog(text="Division attempt finished");
}<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>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
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
try {
throw "Something specific went wrong";
} catch (any e) {
dump(e); // full structure, including the stack trace
// or:
echo(e); // a simpler, shorter representation
}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
try {
riskyOperation();
} catch (any e) {
writeLog(text="Logging before rethrow: " & e.message);
rethrow;
}try {
processPayment();
} catch (any e) {
throw(message="Payment batch failed", cause=e);
}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.