{"record":{"id":"0beb776c6a131acb","repo":"angular/angular","slug":"promise-resolved-with-itself","errorCode":null,"errorMessage":"Promise resolved with itself","messagePattern":"Promise resolved with itself","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/zone.js/lib/common/promise.ts","lineNumber":144,"sourceCode":"          }\n          wasCalled = true;\n          wrappedFunction.apply(null, arguments);\n        };\n      };\n    };\n\n    const TYPE_ERROR = 'Promise resolved with itself';\n    const CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace');\n\n    // Promise Resolution\n    function resolvePromise(\n      promise: ZoneAwarePromise<any>,\n      state: boolean,\n      value: any,\n    ): ZoneAwarePromise<any> {\n      const onceWrapper = once();\n      if (promise === value) {\n        throw new TypeError(TYPE_ERROR);\n      }\n      if ((promise as any)[symbolState] === UNRESOLVED) {\n        // should only get value.then once based on promise spec.\n        let then: any = null;\n        try {\n          if (typeof value === 'object' || typeof value === 'function') {\n            then = value && value.then;\n          }\n        } catch (err) {\n          onceWrapper(() => {\n            resolvePromise(promise, false, err);\n          })();\n          return promise;\n        }\n        // if (value instanceof ZoneAwarePromise) {\n        if (\n          state !== REJECTED &&\n          value instanceof ZoneAwarePromise &&","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/zone.js/lib/common/promise.ts#L126-L162","documentation":"Thrown by zone.js's patched Promise resolution (promise.ts:144): resolving a promise with the very same promise object creates an unresolvable cycle, so resolvePromise() throws TypeError('Promise resolved with itself'), matching the native spec behavior (ChTypeError).","triggerScenarios":"resolve(p) called with p === the promise being resolved: e.g. promise.then(() => promise) chains, assigning a Deferred's promise back into its own resolver, or reassigning a variable to a promise that resolves to itself in async refactoring.","commonSituations":"Hand-rolled deferred wrappers (let p = new Promise(r => ...); p.resolve(p)); retry/polling logic that sets promise = promise.then(...) and then resolves with it; porting Promise A+ style code.","solutions":["Resolve with a fresh promise or the underlying value, never the promise itself.","In a Deferred, keep the original promise in a separate field and never pass it to resolve().","Restructure self-referential chains using an explicit loop or a helper like Promise.resolve().then(...)."],"exampleFix":"// before\nconst deferred = {};\ndeferred.promise = new Promise((res) => { deferred.resolve = res; });\ndeferred.resolve(deferred.promise); // cycle!\n\n// after\nconst deferred = {};\ndeferred.promise = new Promise((res) => { deferred.resolve = res; });\ndeferred.resolve('done'); // resolve with a value, not the promise","handlingStrategy":"type-guard","validationCode":"// Guard resolve() inputs in deferred-style helpers\nfunction safeResolve(promise: Promise<any>, value: any) {\n  if (value === promise) throw new TypeError('Refusing to resolve a promise with itself');\n  return promise; // caller proceeds to resolve with value\n}","typeGuard":"function isSelfResolution(promise: unknown, value: unknown): boolean { return promise === value; }","tryCatchPattern":"try { resolve(maybePromise); } catch (e: any) { if (/resolved with itself/.test(e.message)) { resolve(undefined); /* break the cycle with a real value */ } else throw e; }","preventionTips":["In Deferred wrappers, store the promise in a field never passed to resolve.","Code-review promise chains for 'p = p.then(...)' reassignments later resolved as values."],"tags":["zone-js","promise","async","logic-error"],"backgroundTag":"promise-resolved-with-itself","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}