emberjs/ember.js · error · Error
Cannot call `.lookup('${fullName}')` after the owner has bee
Error message
Cannot call `.lookup('${fullName}')` after the owner has been destroyed What it means
Container#lookup refuses to resolve any factory once the owner (application/instance) has been destroyed. Ember destroys owners during teardown (e.g. app.destroy() or test teardown); calling into a destroyed container is always a lifecycle bug, so it throws instead of returning stale objects.
Source
Thrown at packages/@ember/-internals/container/lib/container.ts:158
let registry = new Registry();
let container = registry.container();
registry.register('api:twitter', Twitter);
let twitter = container.lookup('api:twitter', { singleton: false });
let twitter2 = container.lookup('api:twitter', { singleton: false });
twitter === twitter2; //=> false
```
@private
@method lookup
@param {String} fullName
@param {RegisterOptions} [options]
@return {any}
*/
lookup(
fullName: string,
options?: RegisterOptions
): InternalFactory<object> | object | undefined {
if (this.isDestroyed) {
throw new Error(`Cannot call \`.lookup('${fullName}')\` after the owner has been destroyed`);
}
assert('fullName must be a proper full name', this.registry.isValidFullName(fullName));
return lookup(this, this.registry.normalize(fullName), options);
}
/**
A depth first traversal, destroying the container, its descendant containers and all
their managed objects.
@private
@method destroy
*/
destroy(): void {
this.isDestroying = true;
destroyDestroyables(this);
}
finalizeDestroy(): void {View on GitHub (pinned to 26f97246a8)
Solutions
- Ensure all async work referencing the owner completes or is cancelled before destroy()
- Re-check lifecycle: only call lookup while the app/instance is running
- Remove or tear down event listeners/timers in willDestroy
- In tests, await settled state before teardown (use ember-test-waiters / settled())
Example fix
// before
setTimeout(() => this.owner.lookup('service:session'), 5000);
// after
timer = setTimeout(() => {
if (!this.isDestroying) this.owner.lookup('service:session');
}, 5000); Defensive patterns
Strategy: validation
Validate before calling
if (owner.isDestroying || owner.isDestroyed) return; // skip lookup
Type guard
function isOwnerLive(owner) { return !owner.isDestroyed && !owner.isDestroying; } Try / catch
try { return owner.lookup('service:foo'); } catch (e) { if (String(e.message).includes('after the owner has been destroyed')) return null; throw e; } Prevention
- Check isDestroying/isDestroyed before owner access in async code
- Clean up timers/listeners in willDestroy
- Await settled() in tests before teardown
- Avoid caching owner references across lifecycle boundaries
When it happens
Trigger: Calling owner.lookup('service:foo') (directly or via controllerFor) after the owner's destroy() has run — e.g. in a setTimeout/async callback, an event listener not cleaned up, or code running after application.destroy().
Common situations: Tests hitting the error after teardown due to unresolved promises or lingering timers; app teardown while background jobs still call lookup; accessing a cached owner reference after restart in fastboot or engine teardown.
Related errors
- Cannot call `.factoryFor('${fullName}')` after the owner has
- You attempted to set "${String(prop)}" on a factory manager
- Could not create factory
- Cannot create new instances after the owner has been destroy
- The API deprecated by ${options.id} was removed in ember-sou
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/285f2d5eb463e53a.
Report an issue: GitHub.