5

When thrown from a promise every Error my custom error handler is getting does loose its type

import { HttpErrorResponse } from "@angular/common/http";
import { ErrorHandler, Injectable, Injector, NgZone } from "@angular/core";
import { MatSnackBar } from "@angular/material";

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

    constructor(private injector: Injector) { }

    handleError(error: any): void {
        if (error instanceof HttpErrorResponse) // this needs to be triggered
            this.injector.get(NgZone).run(() => this.injector.get(MatSnackBar).open(error.message))

        console.error(error)
    }

}

findProject(2) will throw a HttpErrorResponse since project 2 does not exist.

Working

this.projectService.findProject(2).subscribe()

Not working

await this.projectService.findProject(2).toPromise()

Not working

await this.projectService.findProject(2).toPromise().catch(error => { throw error })

Not working

try {
  await this.projectService.findProject(2).toPromise()
} catch (e) {
  console.log(e instanceof HttpErrorResponse) // true
  throw e
}

ProjectService is a swagger generated class which returns an Observable

Edit: This is the error object in handleError method:

Error: Uncaught (in promise): HttpErrorResponse: {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":404,"statusText":"OK","url":"http://localhost:9090/api/project/2","ok":false,"name":"HttpErrorResponse","message":"Http failure response for http://localhost:9090/api/project/2: 404 OK","error":{"timestamp":1534921795114,"status":404,"error":"Not Found","exception":"de.dlh.lhind.lhindquiz.controller.ResourceNotFoundException","message":"No message available","path":"/api/project/2"}}
    at resolvePromise (zone.js:814)
    at zone.js:724
    at rejected (main.js:105)
    at ...

It seems like the promise wraps the HttpErrorResponse around a regular Error and error.message is indeed the requested object

3
  • Without going into the if statement, log out 'error', what does it say it's type is? Commented Aug 21, 2018 at 14:57
  • Added to the question Commented Aug 22, 2018 at 7:16
  • Have a very similar issue. Within a promise stream it won't work, but will work with a subscription stream. Commented Sep 21, 2018 at 20:28

2 Answers 2

24

I just hit the same issue and stumbled upon your question.

Seems you can fix this (at least in Angular 7) by unwrapping the exception in your ErrorHandler if needed.

if (error.promise && error.rejection) {
    // Promise rejection wrapped by zone.js
    error = error.rejection;
}

// regular error handling code

Note: I figured out the structure of the wrapping Error object using console.error("%O", error) as per this question: Chrome: Print exception details to console

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks got the same issue in an Ionic Angular Cordova app, specially in iOS app. This line solves the issue. All errors thrown from an unawaited async method, Angular Error Handler catches them and returns them as a Promise.
When doing it like this, the error message sent by server in { error: { message: "could not read results from json files" } } ends up like this: error: "{\"message\":\"could not read results from json files\"}\n"
1

You can "Disable wrapping uncaught promise rejection" by setting DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION. Follow the Angular guide and see the configuration.

In short:

  1. Create a zone-flags.ts file with:
(window as any).__zone_symbol__DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION = true;
  1. Insert the following in polyfills.ts before import 'zone.js';:
import `./zone-flags`;

This might work best if you only throw Error objects and not strings.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.