angular/angular · error · TypeError
Promise resolved with itself
Error message
Promise resolved with itself
What it means
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).
Source
Thrown at packages/zone.js/lib/common/promise.ts:144
}
wasCalled = true;
wrappedFunction.apply(null, arguments);
};
};
};
const TYPE_ERROR = 'Promise resolved with itself';
const CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace');
// Promise Resolution
function resolvePromise(
promise: ZoneAwarePromise<any>,
state: boolean,
value: any,
): ZoneAwarePromise<any> {
const onceWrapper = once();
if (promise === value) {
throw new TypeError(TYPE_ERROR);
}
if ((promise as any)[symbolState] === UNRESOLVED) {
// should only get value.then once based on promise spec.
let then: any = null;
try {
if (typeof value === 'object' || typeof value === 'function') {
then = value && value.then;
}
} catch (err) {
onceWrapper(() => {
resolvePromise(promise, false, err);
})();
return promise;
}
// if (value instanceof ZoneAwarePromise) {
if (
state !== REJECTED &&
value instanceof ZoneAwarePromise &&View on GitHub (pinned to 51cb07e980)
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(...).
Example fix
// before
const deferred = {};
deferred.promise = new Promise((res) => { deferred.resolve = res; });
deferred.resolve(deferred.promise); // cycle!
// after
const deferred = {};
deferred.promise = new Promise((res) => { deferred.resolve = res; });
deferred.resolve('done'); // resolve with a value, not the promise Defensive patterns
Strategy: type-guard
Validate before calling
// Guard resolve() inputs in deferred-style helpers
function safeResolve(promise: Promise<any>, value: any) {
if (value === promise) throw new TypeError('Refusing to resolve a promise with itself');
return promise; // caller proceeds to resolve with value
} Type guard
function isSelfResolution(promise: unknown, value: unknown): boolean { return promise === value; } Try / catch
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; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Uncaught (in promise): ${readableObjectToString(value)}${val
- Must be an instanceof Promise.
- Zone.js has detected that ZoneAwarePromise `(window|global).
- Tried too often to get the ending mark: ${loopCount}
- can capture frames only once per benchmark run
AI-assisted analysis of angular/angular@51cb07e980 (2026-08-22).
Data as JSON: /api/errors/0beb776c6a131acb.
Report an issue: GitHub.