The fail() method registers an error callback on a jQuery Deferred. It runs when the operation is rejected — network failures, validation errors, or explicit reject() calls. This tutorial covers syntax, five examples, comparisons with done() and catch(), and best practices.
01
Syntax
dfd.fail(fn)
02
On reject
Failure only
03
vs done()
Success separate
04
= catch()
jQuery 3+ alias
05
AJAX
$.ajax().fail()
06
Since 1.5
Core Deferred API
Fundamentals
Introduction
Robust apps plan for failure. Servers return errors, networks drop, and user input fails validation. jQuery’s fail() method is the dedicated error path on a Deferred — the mirror image of done() for success.
Chain fail() after async work to log errors, show messages, retry requests, or fall back to cached data. Always pair it with done() (or handle both in then()) so neither outcome is ignored.
Concept
Understanding the fail() Method
fail() is part of jQuery’s Deferred Object API (since jQuery 1.5). Calling deferred.fail(errorHandler) queues your function. When the Deferred enters the rejected state — via reject(), a failed AJAX call, or a rejected promise in a chain — jQuery invokes each fail callback with the rejection arguments.
fail() does not run on success. Resolved Deferreds skip fail handlers and run done() instead.
💡
Beginner Tip
On jQuery 3+, catch() is an alias for fail(). If you prefer Promise-style code, use catch(); legacy tutorials and AJAX examples often use fail() — they are interchangeable.
Foundation
📝 Syntax
General form of deferred.fail:
jQuery
deferred.fail( failCallback [, failCallback ] )
Parameters
failCallback — function executed when the Deferred rejects. Receives reject arguments (error message, jqXHR, status text, etc.). You may register multiple handlers.
Return value
Returns the same Deferred object for chaining done(), always(), or another fail().
Animation effects — recover or notify when an animation callback rejects.
Promise chains — centralize error handling at the end of multi-step async pipelines.
Timeouts — reject when work exceeds a limit and show a timeout message in fail().
Fallback data — load cached content or default values when the primary request fails.
🧠 How fail() Runs on Reject
1
Register
dfd.fail(fn) queues your error callback while pending or already rejected.
Queue
2
Reject
Async work fails; reject(reason) moves state to rejected.
Failure
3
Callbacks fire
Each fail handler runs in order with reject arguments.
Handle
=
🛡
Graceful UX
Users see helpful errors — add always() for spinner cleanup.
Important
📝 Notes
fail() never runs when the Deferred resolves — use done() for success.
In jQuery 3+, catch(fn) is identical to fail(fn).
Empty fail() handlers hide errors from users — always log or display something useful.
Returning a value from fail() does not recover the chain; use catch recovery patterns or a new resolve in advanced cases.
Check rejection state with state() or isRejected() when debugging.
Compatibility
Browser Support
deferred.fail() has been available since jQuery 1.5. It works wherever jQuery Deferred runs — no separate polyfill needed.
✓ jQuery 1.5+
jQuery Deferred.fail()
Supported in jQuery 1.5+, 2.x, and 3.x across all browsers your jQuery build targets.
100%With jQuery loaded
Google ChromeAll versions · Desktop & Mobile
Full support
Mozilla FirefoxAll versions · Desktop & Mobile
Full support
Apple SafariAll versions · macOS & iOS
Full support
Microsoft EdgeAll versions · Chromium & Legacy
Full support
Internet ExplorerIE 6+ · Legacy environments
Full support
OperaAll modern versions
Full support
deferred.fail()Universal
Bottom line: Safe in legacy and modern jQuery projects. For new code without jQuery, native Promise .catch() is the equivalent error handler.
Wrap Up
🎉 Conclusion
The deferred.fail() method is jQuery’s dedicated error handler. Register callbacks for rejections, log meaningful details, show user-friendly messages, and always pair with done() so both outcomes are covered.
Practice the five examples above, then explore isRejected() to check whether a Deferred failed before acting on it.
Implement fallbacks when primary data is unavailable
Test failure paths, not just happy paths
❌ Don’t
Swallow errors with empty fail handlers
Assume fail() runs on success
Expose raw server errors directly to users
Forget always() for spinner cleanup
Ignore rejections in long promise chains
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about fail()
Your error path for jQuery async work.
5
Core concepts
📝01
Syntax
dfd.fail(fn)
API
❌02
Reject
Failure only
Trigger
=03
catch()
jQuery 3+ alias
Alias
🔗04
+ done()
Both paths
Pair
⏰05
Late fn
Still runs
Tip
❓ Frequently Asked Questions
fail() registers a callback that runs when the Deferred is rejected (failure). The handler receives whatever values were passed to reject() or rejectWith() — often an error message, status string, or jqXHR details.
fail() runs only on reject. done() runs only on resolve. For every async operation, register both (or use then with two callbacks) so users see feedback on success and failure.
In jQuery 3.0+, catch() is an alias for fail() on Deferred and Promise objects. They behave the same — catch() exists for Promise-style naming.
Yes. Each fail callback is queued and executed in registration order when the Deferred rejects.
Yes. If the Deferred is already rejected, new fail() handlers fire immediately with the rejection reason.
Yes. jqXHR objects support .fail(function(xhr, status, error) { ... }) — the classic jQuery AJAX error handler pattern.
Did you know?
jQuery’s old $.ajax({ error: fn }) option still works, but chaining .fail() on the returned jqXHR is more flexible — you can attach multiple error handlers from different modules on the same request.