I tried to create a custom global ErrorHandler and followed the instruction detailed here
application-error-handler (just the important parts)
@Injectable() export class ApplicationErrorHandler extends ErrorHandler { constructor(private injector: Injector) { super(false); } handleError(error: any): void { if (error instanceof ApplicationError || error.originalError instanceof ApplicationError) { this.addError(error.originalError); } else { super.handleError(error); } }
app-module
providers: [ { provide: ErrorHandler, useClass: ApplicationErrorHandler } ],
app.component (only the important part)
public ngOnInit(): void { const error = new ApplicationError(); error.message = "fehler"; throw error; }
application-error
export class ApplicationError implements Error { name: string; message: string; httpStatus?: number = 404; applicationStatus?: number; errorMessageTranslationkey: string; handled: boolean = false; }
in my app.component I throw an ApplicationError (in ngOnInit), my ErrorHandler gets called successfully.
But my error inhandleError
is always of typeError
anderror.originalError
is alwaysundefined
no matter if I throw my custom error and there theif
will never resolve to true.I have no idea why and how this happens.
What I see is that the error gets, so I assume, wrapped because when I debug I seeerror: Error: [object: Object] at viewWrappedDebugError (vendor.bundle.js)
Any idea what might cause this issue and how I can resolve it?
EDIT
As suspected it has something to do with Debugmode. As soon as I enable prodmode withenableProdMode();
it works as expected.Still this doesn’t really answer my question yet.
How can I handle my custom error in angular’s debug mode?
Answer
You encounter this problem because ApplicationError
is not an Error
.
You can use the following code in order to create a custom error:
export class ApplicationError extends Error {
httpStatus?: number = 404;
applicationStatus?: number;
errorMessageTranslationkey: string;
handled: boolean = false;
constructor(message?: string) {
super(message);
this.name = ApplicationError.name;
Object.setPrototypeOf(this, ApplicationError.prototype);
}
}
Related to the topic of creating a custom error, check also these links in order to have a full idea on the subject:
Why this needs to be an instance of Error?
Because your error pass through the following method:
function viewWrappedDebugError(err, context) {
if (!(err instanceof Error)) {
// errors that are not Error instances don't have a stack,
// so it is ok to wrap them into a new Error object...
err = new Error(err.toString());
}
_addDebugContext(err, context);
return err;
}
Code available at errors.ts
.
Therefore if you are not throwing an Error
instance, then a new instance is created.
Intercepting uncatched promises in ErrorHandler
Another error case is when you return a promise which becomes rejected, from your method that is called by the Angular lifecycle (eg: handler, lifecycle-hook).
export class AppComponent implements OnInit {
ngOnInit() {
return new Promise((resolve, reject) => reject(new ApplicationError()));
}
}
Therefore the error handling code can look like:
import {ErrorHandler, Injectable, Injector} from "@angular/core";
import {ApplicationError} from "./ApplicationError";
@Injectable()
export class ApplicationErrorHandler extends ErrorHandler {
private errors: ApplicationError[] = [];
constructor(private injector: Injector) {
super(false);
}
handleError(error: any): void {
if (error instanceof ApplicationError) {
this.addError(error);
}
else {
if(error.rejection instanceof ApplicationError) {
this.addError(error.rejection);
}
else {
super.handleError(error);
}
}
}
addError(error: ApplicationError) {
this.errors.push(error);
}
}
Attribution
Source : Link , Question Author : Arikael , Answer Author : andreim