OrchardCMS/OrchardCore · error · TypeError
Thenable self-resolution
Error message
Thenable self-resolution
What it means
Same Promises/A+ self-resolution guard as the full build: jQuery's Deferred (present in the slim build) throws this TypeError when a resolution handler returns the very promise being resolved, which would create an unresolvable cycle.
Solutions
- Find the handler in the stack that returns the promise and return a new Deferred's promise, a plain value, or another (different) promise instead.
- Add a guard before resolving: throw if the candidate value === the deferred's own promise.
- Refactor shared deferreds so each logical operation creates its own Deferred instance.
- Prefer native Promises or $.when over manually returning deferred.promise() inside its own chains.
Example fix
// before
promise.then(function loop() {
return promise; // TypeError: Thenable self-resolution
});
// after
promise.then(function (v) {
return retry(v); // return a NEW promise
}); Defensive patterns
Strategy: type-guard
Validate before calling
function resolveSafely(d, v) {
if (v && v.then && v === d.promise()) { return $.Deferred().reject(new TypeError('self-resolution blocked')); }
d.resolve(v);
} Type guard
function isThenable(v) { return !!v && (typeof v === 'object' || typeof v === 'function') && typeof v.then === 'function'; }
function isOwnPromise(d, v) { return isThenable(v) && v === d.promise(); } Try / catch
$.when(promise).then(h).fail(function (e) { if (e && e.message === 'Thenable self-resolution') { recoverChain(); } }); Prevention
- Return new promises from then handlers, never the chained promise itself.
- Avoid shared global Deferreds; scope them per call.
- Add invariant checks before resolve() in wrapper utilities.
- Consider native Promise implementations during refactors.
When it happens
Trigger: A .then()/.pipe()/.state()-chain handler returning the same deferred.promise(); resolving a deferred with its own promise object.
Common situations: Retry/recursion wrappers accidentally returning the outer deferred; shared module-level deferreds reused across calls; callback-to-promise refactors that return the same promise from within its own then handler.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
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/7a5c8fc77b0a11d4.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.5.1/jquery.slim.js:3767
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)