{"record":{"id":"6a3f7d08823377f6","repo":"angular/angular","slug":"uncaught-in-promise-readableobjecttostring-va","errorCode":null,"errorMessage":"Uncaught (in promise): ${readableObjectToString(value)}${value && value.stack ? '\\n' + value.stack : ''}","messagePattern":"Uncaught \\(in promise\\): (.+?)(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zone.js/lib/common/promise.ts","lineNumber":225,"sourceCode":"                configurable: true,\n                enumerable: false,\n                writable: true,\n                value: trace,\n              });\n            }\n          }\n\n          for (let i = 0; i < queue.length;) {\n            scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);\n          }\n          if (queue.length == 0 && state == REJECTED) {\n            (promise as any)[symbolState] = REJECTED_NO_CATCH;\n            let uncaughtPromiseError = value;\n            try {\n              // Here we throws a new Error to print more readable error log\n              // and if the value is not an error, zone.js builds an `Error`\n              // Object here to attach the stack information.\n              throw new Error(\n                'Uncaught (in promise): ' +\n                  readableObjectToString(value) +\n                  (value && value.stack ? '\\n' + value.stack : ''),\n              );\n            } catch (err) {\n              uncaughtPromiseError = err;\n            }\n            if (isDisableWrappingUncaughtPromiseRejection) {\n              // If disable wrapping uncaught promise reject\n              // use the value instead of wrapping it.\n              uncaughtPromiseError.throwOriginal = true;\n            }\n            uncaughtPromiseError.rejection = value;\n            uncaughtPromiseError.promise = promise;\n            uncaughtPromiseError.zone = Zone.current;\n            uncaughtPromiseError.task = Zone.currentTask!;\n            _uncaughtPromiseErrors.push(uncaughtPromiseError);\n            api.scheduleMicroTask(); // to make sure that it is running","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/angular/angular/blob/51cb07e98081ab7e4e84a9e0949266a8e19cca84/packages/zone.js/lib/common/promise.ts#L207-L243","documentation":"Not a thrown error you catch, but zone.js's unhandled-rejection reporting: when a rejected ZoneAwarePromise finishes its callback queue with no rejection handler, zone.js builds a readable Error ('Uncaught (in promise): ' + value) to attach stack info and routes it to Zone.onUnhandledError / window.onerror. The property throwOriginal may be set to surface the raw rejection value instead.","triggerScenarios":"A promise rejects and no .catch/onRejection is attached before the microtask queue drains (symbolState becomes REJECTED_NO_CATCH): missing .catch on fetch calls, async functions invoked without await/catch, fire-and-forget tasks.","commonSituations":"Angular apps calling this.http.get(...).subscribe-less or promise-based APIs without error handlers; test environments reporting 'Uncaught (in promise)' in console; regressions where a .catch was dropped during refactor.","solutions":["Attach .catch(...) (or try/catch around await) to every promise that can reject.","For observables, provide an error handler to subscribe: source.subscribe(next, err => ...).","Register a global handler (window.addEventListener('unhandledrejection', ...) or Zone's onUnhandledError via ERROR_COOPERATIVE_GLOBAL_SCHEDULING-style config) to log and triage.","Set global[__zone_symbol__ignoreConsoleErrorUncaughtError] = true only as a temporary suppress, then fix the root causes."],"exampleFix":"// before\nthis.http.get('/api/heroes').toPromise(); // rejection unhandled\n\n// after\ntry { const heroes = await this.http.get('/api/heroes').toPromise(); }\ncatch (e) { this.logger.error(e); }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Surface unhandled rejections globally for triage instead of letting them vanish\nwindow.addEventListener('unhandledrejection', (event) => {\n  logger.error('Unhandled rejection:', event.reason);\n});","preventionTips":["Attach .catch or try/catch-await to every promise you create or call.","Enable strict TypeScript checks and lint rules (e.g. no-floating-promises) to catch unhandled promises at build time.","Treat every 'Uncaught (in promise)' in CI logs as a failing signal."],"tags":["zone-js","promise","unhandled-rejection","angular"],"backgroundTag":"unhandled-promise-rejection","analyzedSha":"51cb07e98081ab7e4e84a9e0949266a8e19cca84","analyzedAt":"2026-08-22T07:04:54.531Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}