OrchardCMS/OrchardCore · error · TypeError

Thenable self-resolution

Error message

Thenable self-resolution

What it means

Same Promises/A+ guard as in jquery.js, present in jquery.slim.js: a jQuery Deferred throws TypeError "Thenable self-resolution" when a promise is resolved (or a .then handler returns) with the promise object itself. Self-resolution would loop forever, so the spec mandates rejection with this TypeError.

Solutions

  1. Resolve with the concrete value or a distinct promise, never the same promise/deferred object.
  2. Audit .then() callbacks for returns of the outer promise variable; return the payload or a new promise instead.
  3. Restructure recursive promise code so each recursion creates a fresh deferred, or convert to async/await.
  4. Guard with a check: if (value === myPromise) throw/handle before resolving.

Example fix

// before
promise.then(function () {
  return promise; // self-resolution
});

// after
promise.then(function (result) {
  return process(result); // return a value or a different promise
});
Defensive patterns

Strategy: type-guard

Validate before calling

function resolveSafe(deferred, value) {
  if (value && (value === deferred || value === deferred.promise())) return; // skip self-resolution
  deferred.resolve(value);
}

Type guard

function isSamePromise(p, v) { return v === p; }

Try / catch

promise.catch(function (err) {
  if (err instanceof TypeError && err.message === 'Thenable self-resolution') {
    // break the cycle: re-run with corrected resolution value
  } else { throw err; }
});

Prevention

When it happens

Trigger: deferred.resolve(deferred.promise()); returning the same promise from inside its own .then() handler; a function that both creates a deferred and resolves it with its own promise (e.g. in recursive or cached-promise patterns).

Common situations: Memoized async functions that cache the promise and pass it back as the resolution value; refactors that accidentally alias the outer promise; chains where a handler intended to return data but returned the chain itself.

Related errors


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

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.6.0/jquery.slim.js:3771

						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)