OrchardCMS/OrchardCore · error · TypeError
Thenable self-resolution
Error message
Thenable self-resolution
What it means
jQuery's promise implementation throws this TypeError during promise resolution when a resolved/rejected value is a thenable that is the promise itself, i.e. a promise resolved with itself. Per Promises/A+ 2.3.1, self-resolution would create an infinite resolution loop, so it must be rejected with this TypeError.
Solutions
- Find the resolve/then call that passes the promise its own value; resolve with the actual data instead (deferred.resolve(data)).
- In .then() handlers, return the computed value or a new/different promise, never the same promise object.
- If you need the settled value of the same chain, capture it in a separate variable or use an inner promise rather than returning the outer one.
- Refactor cyclic deferred usage into async/await, where self-await still throws but is easier to spot (TypeError: Chaining cycle detected).
Example fix
// before
var d = $.Deferred();
function load() {
d.resolve(d.promise()); // self-resolution
return d.promise();
}
// after
var d = $.Deferred();
function load() {
d.resolve(fetchData()); // resolve with actual value or another promise
return d.promise();
} Defensive patterns
Strategy: type-guard
Validate before calling
function safeResolve(deferred, value) {
if (value === deferred || value === deferred.promise()) {
throw new TypeError('Attempted to resolve a deferred with itself');
}
deferred.resolve(value);
} Type guard
function isSelfResolution(deferred, value) { return value != null && (value === deferred || value === deferred.promise()); } Try / catch
p.catch(function (e) {
if (e instanceof TypeError && /Thenable self-resolution/.test(e.message)) {
// handle cyclic promise: recover or report
} else { throw e; }
}); Prevention
- Never return the outer promise from within its own .then() handler.
- Resolve deferreds with data values or fresh promises, not the deferred's own promise.
- In recursive async code, create a new deferred/promise per recursion level.
- Add a debug assertion comparing resolution values against the promise identity in dev builds.
When it happens
Trigger: Calling deferred.resolve(deferred.promise()) or resolving a jQuery promise with itself; inside a .then() handler returning the same promise object the handler belongs to; cyclic chains like p.then(function(){ return p; }); patterns where a deferred is resolved with its own promise in async recursion.
Common situations: Recursive async code that caches its own promise and passes it back as the success value; refactored code where a variable accidentally references the same deferred/promise; misused .then() chains where the return value of the callback is the outer promise rather than a plain value or a different thenable.
Related errors
- Thenable self-resolution
- Thenable self-resolution
- Thenable self-resolution
- Thenable self-resolution
- Thenable self-resolution
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/442abe58b763a145.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.6.0/jquery.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)