jQuery Deferred fail() Method

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Error handlers

What You’ll Learn

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

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.

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.

📝 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().

AJAX example

jQuery
$.ajax({
  url: "/api/profile",
  method: "GET"
})
  .done(function (response) {
    renderProfile(response);
  })
  .fail(function (xhr, status, error) {
    console.error("Request failed:", status, error);
  });

⚡ Quick Reference

GoalCode
Error handlerdfd.fail(fn)
Promise-style (jQuery 3+)dfd.catch(fn)
Success handlerdfd.done(fn)
Either outcome cleanupdfd.always(fn)
Trigger rejectiondfd.reject(reason)

📋 fail() vs done() vs catch()

Each handler responds to a different Deferred outcome.

fail()
on reject

jQuery error path

catch()
on reject

Alias (jQuery 3+)

done()
on resolve

Success path

always()
on either

Shared cleanup

Examples Gallery

Each example demonstrates error handling with jQuery Deferred. Use DevTools or the Try-it links to run them.

📚 Getting Started

Attach fail() and reject with an error reason.

Example 1 — Basic Error Handler

Register fail(), then call reject() with an error message.

jQuery
const dfd = $.Deferred();

dfd.fail(function (error) {
  console.error("fail:", error);
});

dfd.reject("Network error");
Try It Yourself

How It Works

reject() settles the Deferred as failed. Queued fail() handlers run with the rejection reason; done() handlers are skipped.

Example 2 — done() and fail() Together

Handle success and failure in separate callbacks — the standard AJAX pattern.

jQuery
$.ajax({
  url: "/api/profile",
  method: "GET"
})
  .done(function (response) {
    console.log("Success:", response);
  })
  .fail(function (xhr, status, error) {
    console.error("Request failed:", status, error);
  });
Try It Yourself

How It Works

Real $.ajax().fail() receives xhr, status, and error. The try-it simulates reject with status and error arguments the same way.

📈 Practical Patterns

Multiple listeners, UI feedback, and late registration.

Example 3 — Multiple fail() Handlers

Split error work across logging, user notifications, and monitoring.

jQuery
const dfd = $.Deferred();

dfd.fail(function (err) {
  console.error("Log:", err);
});

dfd.fail(function (err) {
  showToast("Error: " + err);
});

dfd.fail(function () {
  reportToMonitoring("request_failed");
});

dfd.reject("timeout");
Try It Yourself

How It Works

Every fail() handler runs in registration order when the Deferred rejects — useful when different modules attach their own error listeners.

Example 4 — User-Facing Error Message

Show a friendly message when a simulated request fails.

jQuery
function fetchItems() {
  const dfd = $.Deferred();

  setTimeout(function () {
    dfd.reject("503 Service Unavailable");
  }, 600);

  return dfd
    .done(function (items) {
      $("#list").text(items.join(", "));
    })
    .fail(function (error) {
      $("#list").text("Could not load items — " + error);
    });
}
Try It Yourself

How It Works

Users should always see feedback on failure. Pair this with always() to hide spinners regardless of outcome.

Example 5 — Register fail() After Reject

Handlers added after settlement still run if the Deferred already rejected.

jQuery
const dfd = $.Deferred();

dfd.reject("already failed");

dfd.fail(function (reason) {
  console.error("fail (registered late):", reason);
});
Try It Yourself

How It Works

Rejected Deferreds remember their reason. Late fail() handlers execute immediately — the same behavior as late done() on resolved Deferreds.

🚀 Use Cases

  • AJAX requests — handle network errors, HTTP 4xx/5xx, and invalid JSON responses.
  • 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.

📝 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.

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 Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All 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.

🎉 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.

💡 Best Practices

✅ Do

  • Pair every done() with a fail() handler
  • Log specific error context for debugging
  • Show clear user-facing messages on failure
  • 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

Key Takeaways

Knowledge Unlocked

Five things to remember about fail()

Your error path for jQuery async work.

5
Core concepts
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.

Continue to isRejected()

Learn how to check if a Deferred is in the rejected state.

isRejected() tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful