{"record":{"id":"442abe58b763a145","repo":"OrchardCMS/OrchardCore","slug":"thenable-self-resolution-442abe","errorCode":null,"errorMessage":"Thenable self-resolution","messagePattern":"Thenable self-resolution","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.6.0/jquery.js","lineNumber":3771,"sourceCode":"\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n","sourceCodeStart":3753,"sourceCodeEnd":3789,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Resources/wwwroot/Vendor/jquery-3.6.0/jquery.js#L3753-L3789","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nvar d = $.Deferred();\nfunction load() {\n  d.resolve(d.promise()); // self-resolution\n  return d.promise();\n}\n\n// after\nvar d = $.Deferred();\nfunction load() {\n  d.resolve(fetchData()); // resolve with actual value or another promise\n  return d.promise();\n}","handlingStrategy":"type-guard","validationCode":"function safeResolve(deferred, value) {\n  if (value === deferred || value === deferred.promise()) {\n    throw new TypeError('Attempted to resolve a deferred with itself');\n  }\n  deferred.resolve(value);\n}","typeGuard":"function isSelfResolution(deferred, value) { return value != null && (value === deferred || value === deferred.promise()); }","tryCatchPattern":"p.catch(function (e) {\n  if (e instanceof TypeError && /Thenable self-resolution/.test(e.message)) {\n    // handle cyclic promise: recover or report\n  } else { throw e; }\n});","preventionTips":["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."],"tags":["jquery","promise","deferred","async"],"backgroundTag":"promise-self-resolution","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}