OrchardCMS/OrchardCore · error · TypeError

Thenable self-resolution

Error message

Thenable self-resolution

What it means

jQuery's Deferred implementation throws this TypeError when a promise handler (an added done/fail/progress/then callback) returns the same deferred's own promise, which would make the promise resolve itself — a cycle forbidden by Promises/A+ (section 2.3.1). jQuery aborts to prevent infinite recursion.

Solutions

  1. Return a new promise/value from the handler, never the same deferred.promise()
  2. Return a distinct thenable or plain value to chain properly
  3. Restructure so the deferred used for resolution is created outside and not returned by its own handlers
  4. Use native Promises, which reject cycles with 'Chaining cycle detected' instead

Example fix

// before
var d = $.Deferred();
d.then(function () { return d.promise(); }); // TypeError: Thenable self-resolution
// after
var d = $.Deferred();
d.then(function (v) { return v; });
Defensive patterns

Strategy: type-guard

Validate before calling

function returnsSelf(deferred, handler) { return handler && deferred.promise !== undefined; }

Type guard

function isSamePromise(returned, deferred) { return returned === deferred.promise(); }

Try / catch

try { d.then(handler); } catch (e) { if (e instanceof TypeError && e.message === 'Thenable self-resolution') { console.error('Handler returned its own promise'); } else { throw e; } }

Prevention

When it happens

Trigger: Inside a .then/.done handler on a jQuery deferred, returning the same deferred.promise() object, e.g. `d.then(function(){ return d.promise(); })`, or returning a thenable that is the promise itself.

Common situations: Chaining code that accidentally returns the original promise instead of a new one; reusing a deferred variable in a closure inside its own handler; refactored promise chains creating self-referential returns.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/144137a3b8d5b363. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.4.1/jquery.js:3562

						return function() {
							var that = this,
								args = arguments,
								mightThrow = function() {
									var returned, then;

									// Support: Promises/A+ section 2.3.3.3.3
									// https://promisesaplus.com/#point-59
									// Ignore double-resolution attempts
									if ( depth < maxDepth ) {
										return;
									}

									returned = handler.apply( that, args );

									// Support: Promises/A+ section 2.3.1
									// https://promisesaplus.com/#point-48
									if ( returned === deferred.promise() ) {
										throw new TypeError( "Thenable self-resolution" );
									}

									// Support: Promises/A+ sections 2.3.3.1, 3.5
									// https://promisesaplus.com/#point-54
									// https://promisesaplus.com/#point-75
									// Retrieve `then` only once
									then = returned &&

										// Support: Promises/A+ section 2.3.4
										// https://promisesaplus.com/#point-64
										// Only check objects and functions for thenability
										( typeof returned === "object" ||
											typeof returned === "function" ) &&
										returned.then;

									// Handle a returned thenable
									if ( isFunction( then ) ) {

View on GitHub (pinned to 4306c0717f)