{"record":{"id":"cdfb7191040bfa53","repo":"emberjs/ember.js","slug":"promiseproxy-s-promise-must-be-set","errorCode":null,"errorMessage":"PromiseProxy's promise must be set","messagePattern":"PromiseProxy's promise must be set","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@ember/object/promise-proxy-mixin.ts","lineNumber":232,"sourceCode":"}\nconst PromiseProxyMixin = Mixin[INTERNAL_MIXIN_CREATE]({\n  reason: null,\n\n  isPending: computed('isSettled', function () {\n    return !get(this, 'isSettled');\n  }).readOnly(),\n\n  isSettled: computed('isRejected', 'isFulfilled', function () {\n    return get(this, 'isRejected') || get(this, 'isFulfilled');\n  }).readOnly(),\n\n  isRejected: false,\n\n  isFulfilled: false,\n\n  promise: computed({\n    get() {\n      throw new Error(\"PromiseProxy's promise must be set\");\n    },\n    set(_key, promise: RSVP.Promise<unknown>) {\n      return tap(this, promise);\n    },\n  }),\n\n  then: promiseAlias('then'),\n\n  catch: promiseAlias('catch'),\n\n  finally: promiseAlias('finally'),\n});\n\nfunction promiseAlias<T, N extends MethodNamesOf<Promise<T>>>(name: N) {\n  return function (this: PromiseProxyMixin<T>, ...args: Parameters<Promise<T>[N]>) {\n    let promise = get(this, 'promise');\n\n    // We need this cast because `Parameters` is deferred so that it is not","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@ember/object/promise-proxy-mixin.ts#L214-L250","documentation":"PromiseProxyMixin defines 'promise' as a computed property whose getter throws if the proxy has no promise set. Reading isPending/isRejected/isFulfilled or the promise property on a PromiseProxy (e.g. PromiseProxyMixin.extend({}).create() or an ObjectProxy wrapping nothing) before assigning a promise hits this error.","triggerScenarios":"Accessing proxy.promise or proxy.isPending/isRejected/isFulfilled on a proxy created without an initial promise; passing a non-promise or forgetting to set promise in create({ promise: ... }).","commonSituations":"Computed properties reading isFulfilled before the async load assigns the promise; templates rendering proxy state before setup; create() called without the promise argument.","solutions":["Always create with a promise: PromiseProxy.create({ promise: somePromise })","Guard template/computed access with proxy.promise before reading state flags","Set the promise property via set() which taps the promise automatically"],"exampleFix":"// before\nlet proxy = ObjectProxy.extend(PromiseProxyMixin).create();\n// after\nlet proxy = ObjectProxy.extend(PromiseProxyMixin).create({ promise: loadData() });","handlingStrategy":"validation","validationCode":"let proxy = ObjectProxy.extend(PromiseProxyMixin).create({ promise });\n// guard reads:\nif (proxy.get('promise')) { useProxyState(proxy); }","typeGuard":"function hasPromiseSet(proxy) { try { proxy.get('promise'); return true; } catch { return false; } }","tryCatchPattern":"try { state = proxy.get('isFulfilled'); } catch (e) { if (!/promise must be set/.test(e.message)) throw e; state = null; }","preventionTips":["Always pass promise at create()/setup time","Never read isPending/isRejected/isFulfilled before assigning a promise","Initialize proxies inside async setup where the promise exists"],"tags":["ember","promise","promise-proxy","uninitialized-property"],"backgroundTag":"promise-not-set","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}