cflog records what happened after the fact. Debugging is about inspecting what's happening right now: cfdump (writeDump in CFScript) shows the full contents of a variable, and cfabort stops execution exactly where something looks wrong, so a page doesn't keep running past the point that actually matters.
Learning Objectives
After completing this lesson, you'll be able to:
- Inspect a variable's full contents with cfdump/writeDump.
- Combine cfdump and cfabort to halt execution exactly where something looks wrong.
- Recognize the real engine differences between Adobe's and Lucee's dump and abort behavior.
How Debugging Fits In
Something Looks Wrong
cfdump the Suspect Variable
cfabort — Stop Right There
Inspect the Output, Fix It
A Basic Dump
<cfdump var="#userProfile#" label="userProfile">
writeDump(var = userProfile, label = "userProfile");
cfdump / writeDump's Attributes
| Attribute | Meaning |
|---|---|
| var | The variable to display (required) |
| output | Where it goes: browser (default), console, or a file path |
| format | html (default) or text |
| label | A header shown above the dump output |
| expand | Whether nested structures start expanded (default) or collapsed |
| top | How many rows or nesting levels to show |
| show / hide | Limit the dump to specific keys/columns, or exclude specific ones |
| keys | For a structure, how many keys to display |
| showUDFs | Whether to include user-defined functions in the output |
| abort | When true, stops the request immediately after the dump renders |
abort=true on cfdump itself is a genuinely useful shortcut, it dumps the variable and halts in one line, without a separate cfabort tag.
A Real Example: Dumping an Exception, Then Halting
This is the pattern from earlier in this module put to direct use during development: catch the exception, dump its full contents to see exactly what it is, then stop before anything downstream runs with bad data.
<cftry>
<cfset firstName = userService.getUserById(1).getFirstName()>
<cfcatch type="any">
<cfdump var="#cfcatch#">
<cfabort>
</cfcatch>
</cftry>try {
firstName = userService.getUserById(1).getFirstName();
} catch (any e) {
writeDump(e);
abort;
}cfabort's Attributes
| Attribute | Meaning |
|---|---|
| showError | An error message shown on the standard CFML error page (or routed to a cferror page, if one is defined) when cfabort executes |
cfabort has both a tag form (<cfabort>) and a script form (abort;). It triggers Application.cfc's onAbort method instead of onRequestEnd.
Real Engine Differences
| Aspect | Adobe | Lucee |
|---|---|---|
| dump format options | html or text | html, text, classic, or simple — more choices for the rendered output style |
| dump destinations | browser, console, or a file path | Adds a debug output option alongside browser, console, or a filename |
| abort scope | Not documented as configurable | A type attribute controls whether abort stops the whole request or just the current page (request by default) |
| abort inside a function with output=false | Not a documented concern | Since Lucee 5.3, function output isn't buffered by default, so abort inside a function may not behave as expected unless this.bufferOutput=true is set |
The Lucee buffering caveat is a real gotcha worth knowing before relying on abort inside a function that has output=false set.
Beyond cfdump and cfabort: Line Debugging
Adobe ColdFusion also supports step-through line debugging from an IDE like ColdFusion Builder or Eclipse. It's enabled in the ColdFusion Administrator under Debugging & Logging > Debugger Settings (Allow Line Debugging), with a dedicated debugger port and a maximum number of concurrent sessions. It's a separate, IDE-driven workflow from cfdump/cfabort, worth knowing exists but outside the scope of code-level debugging covered here.
Common Beginner Mistakes
Leaving a cfdump call in production code
A dump can expose sensitive data (passwords, tokens, full session contents) directly in the page output. Gate debug dumps behind an environment check, or remove them before shipping.
Dumping a structure that contains sensitive fields without using hide
hide lets specific keys be excluded from the output, useful for dumping something like a user record without exposing a password hash or API key alongside everything else.
Assuming abort inside a Lucee function always stops execution the same way it would on a page
Since Lucee 5.3, function output isn't buffered by default when output=false, meaning abort inside such a function may not behave as expected unless this.bufferOutput=true is configured.
Not knowing about cfdump's own abort attribute
abort=true on cfdump itself dumps the variable and halts the request in one line, a separate cfabort tag isn't needed just to stop right after a dump.
Best Practices
- Gate debug dumps behind an environment check, or remove them entirely before deploying to production.
- Use hide to redact sensitive fields when dumping a structure that contains them.
- Reach for output="console" during development to avoid a large dump taking over the rendered page.
- Combine cfdump and cfabort (or cfdump's own abort attribute) to stop exactly at the point something looks wrong, rather than letting the request continue on bad data.
Interview Questions
What's the difference between cfdump and cfabort?
cfdump displays a variable's full contents for inspection. cfabort stops the request at that point, returning only what was processed before it. cfdump's own abort attribute can do both in one line.
Why is leaving cfdump calls in production code a real risk?
A dump can expose sensitive data, like a password hash, token, or full session contents, directly in the page output where anyone viewing it could see it.
What does cfabort trigger in Application.cfc, and what does it skip?
It invokes onAbort instead of onRequestEnd.
What's a real Lucee-specific gotcha with abort inside a function?
Since Lucee 5.3, function output isn't buffered by default when output=false, so abort inside such a function may not behave as expected unless this.bufferOutput=true is set.
Summary
In this lesson, you inspected variables with cfdump/writeDump, combined it with cfabort to halt execution exactly where something looks wrong, covered cfabort's real behavior (triggering onAbort, not onRequestEnd), the real engine differences between Adobe and Lucee's dump and abort implementations, and where IDE-based line debugging fits in beyond code-level tools.
What's Next?
This wraps up error handling and debugging. The next module moves into web development: building HTML forms, validating submitted data, and working with URL parameters.