<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <title>ABP.IO Stories</title>
    <link>https://abp.io/community/articles</link>
    <description>A hub for ABP Framework, .NET, and software development. Access articles, tutorials, news, and contribute to the ABP community.</description>
    <lastBuildDate>Fri, 23 Oct 2026 10:54:21 Z</lastBuildDate>
    <generator>Community - ABP.IO</generator>
    <image>
      <url>https://abp.io/assets/favicon.ico/favicon-32x32.png</url>
      <title>ABP.IO Stories</title>
      <link>https://abp.io/community/articles</link>
    </image>
    <a10:link rel="self" type="application/rss+xml" title="self" href="https://abp.io/community/rss?member=sinan" />
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/global-error-handling-in-angular-gjcb2f1e</guid>
      <link>https://abp.io/community/posts/global-error-handling-in-angular-gjcb2f1e</link>
      <a10:author>
        <a10:name>sinan</a10:name>
        <a10:uri>https://abp.io/community/members/sinan</a10:uri>
      </a10:author>
      <category>angular</category>
      <category>error-handling</category>
      <title>Global Error Handling in Angular</title>
      <description>An article about global error handling in angular</description>
      <pubDate>Mon, 12 Feb 2024 16:33:15 Z</pubDate>
      <a10:updated>2026-10-23T07:32:09Z</a10:updated>
      <content:encoded><![CDATA[<h1>Global Error Handling in Angular</h1>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/error_handling.jpg" alt="Error Handling" /></p>
<p>Error handling is how we deal with errors that go wrong when we are running a program. There is no code that runs perfectly forever :) Things can go wrong and your application might crash. <strong>So, in order to run your program smoothly you must handle errors.</strong> It is just not for keeping your application in a running state. It is also useful to show messages about the error to the client. Like what went wrong, why it is not allowed to access this page etc.</p>
<h3>How to handle errors</h3>
<ul>
<li>First of all, you have to catch them 😀. You can catch them via <strong>try-catch block</strong>. See an example;</li>
</ul>
<h4>Create an basic error</h4>
<pre><code class="language-ts">({} as any).doSomething()
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/error-image-1.png" alt="Error Image" /></p>
<h4>Handle it</h4>
<pre><code class="language-ts">try {
  ({} as any).doSomething();
} catch (error) {
  this.toastService.showError(error.message);
}
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/show-toast-2.gif" alt="toast-gif" /></p>
<ul>
<li>See, we catch the error and handle it.</li>
<li>In this case, we know where the error will be thrown. Most of the time we won't know where the error will appear. Should we cover the entire application with try-catch blocks? Of course not 😀</li>
<li><strong>We are going to handle errors globally</strong>. Angular provides a great way to do it. Let's do it step by step;</li>
</ul>
<h3>1.Create a <strong>service</strong> and implement the <strong><code>ErrorHandler</code></strong> interface.</h3>
<pre><code class="language-ts">import { ErrorHandler, Injectable, inject } from '@angular/core';
import { ToastService } from './toast.service';

@Injectable({
  providedIn: 'root'
})
export class CustomErrorHandlerService implements ErrorHandler {
  toastService = inject(ToastService);
  
  //This method comes from interface
  handleError(error: any): void {
    this.toastService.showError(error.message);
  }
}

</code></pre>
<h3>2.Provide the service by using the <strong><code>ErrorHandler</code></strong> class from <strong><code>@angular/core</code></strong>.</h3>
<pre><code class="language-ts">import { ErrorHandler } from '@angular/core';

providers: [
  { provide: ErrorHandler, useExisting: CustomErrorHandlerService }
]

</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/show-toast-2.gif" alt="toast-gif" /></p>
<ul>
<li>It behaves exactly the same. Nice, now we catch the entire errors in one simple service.</li>
<li>Is it that simple? I wish it is but it's not 😀. This handling mechanism only works synchronously. When we start making http requests, our <strong><code>CustomErrorHandlerService</code></strong> won't catch the errors.</li>
</ul>
<h2>How to handle HTTP Requests</h2>
<p>Make an HTTP request and check if it's working.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/http-request-4.gif" alt="http-request" /></p>
<p>As you can see it doesn’t work. So how can we catch the http errors? with <strong><code>catchError()</code></strong> operator in rxjs or <strong><code>observer object</code></strong>. I will go with <strong><code>catchError()</code></strong> operator.</p>
<pre><code class="language-ts">getTodo(id: number) {
  this.http
      .get(`https://jsonplaceholder.typicode.com/todos/${id}`)
      .pipe(catchError((err) =&gt; {
  	 this.toastService.showError(err.message);
	 return EMPTY;
        })
       )
      .subscribe(todo =&gt; this.todo = todo);
}

</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/http-request-5.gif" alt="http-request" /></p>
<ul>
<li>So are we going to add this <strong><code>catchError()</code></strong> operator to the entire http requests? <strong>NO, we will use HTTP Interceptors!</strong></li>
<li>Let's do it step by step.</li>
</ul>
<h3>1.Remove catchError pipe</h3>
<pre><code class="language-ts">getTodo(id: number) {
  this.http.get('https://jsonplaceholder.typicode.com/todos/${id}').subscribe(todo =&gt; this.todo = todo);
}
</code></pre>
<h3>2.Create an HTTP Interceptor</h3>
<pre><code class="language-ts">import { Injectable, inject } from '@angular/core';
import { HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { EMPTY, catchError } from 'rxjs';
import { ToastService } from './toast.service';

@Injectable({
  providedIn: 'root'
})
export class ToastInterceptor implements HttpInterceptor {
  toastService = inject(ToastService);

  intercept(req: HttpRequest&lt;any&gt;, next: HttpHandler) {
    return next.handle(req).pipe(catchError((error) =&gt; {
      this.toastService.showError(error.message);
      return EMPTY;
    }));
  }
}
</code></pre>
<h3>3.Provide the interceptor</h3>
<pre><code class="language-ts">import { HTTP_INTERCEPTORS} from '@angular/common/http';

providers: [
  { provide: HTTP_INTERCEPTORS, useExisting: ToastInterceptor, multi: true }
]
</code></pre>
<p>Now everything has set up. Let's make an HTTP request and try again.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/http-request-5.gif" alt="http-request" /></p>
<ul>
<li>So, now we are handling http errors globally. Whenever an error occurs, it will be catched from interceptor and will be showed via toast message.</li>
<li>But this method has a one little disadvantage. What if we dont want to show toast message for a spesific case? <a href="https://github.com/angular/angular/issues/18155">related issue about this problem</a>.</li>
<li><strong><a href="https://abp.io/">ABP Framework</a> has great solution for this problem. Let's understand the solution and apply it straightforwardly.</strong>
<ul>
<li>Create a singleton service called <strong><code>HttpErrorReporterService</code>.</strong> This service is going to store <strong>HttpError</strong> in a subject, and share the httpError as an observable for subscribers.</li>
<li>Create a new service called <strong><code>RestService</code></strong> which is a layer on top of <strong><code>HttpClient</code></strong>, this new service is able to get a skipHandleError parameter. If skipHandleError value is <strong>false</strong> then it will be reported to the <strong><code>HttpErrorReporterService</code></strong> otherwise error will be throwed.</li>
<li>Create a service called <strong><code>ErrorHandler</code></strong>, This service is going to subscribe to observable in <strong><code>HttpErrorReporterService</code></strong> and handle the errors (in our case we will show toast message).</li>
</ul>
</li>
<li>When i first see this solution, i loved it. For more information and detail you can check the source code from the links below;
<ul>
<li><a href="https://github.com/abpframework/abp/blob/360a3395aa0e44fb77574ea7eac745e8ba94b82e/npm/ng-packs/packages/core/src/lib/services/http-error-reporter.service.ts#L6"><strong>Http Error Reporter Service</strong></a></li>
<li><a href="https://github.com/abpframework/abp/blob/360a3395aa0e44fb77574ea7eac745e8ba94b82e/npm/ng-packs/packages/core/src/lib/services/rest.service.ts#L4"><strong>Rest Service</strong></a></li>
<li><a href="https://github.com/abpframework/abp/blob/360a3395aa0e44fb77574ea7eac745e8ba94b82e/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts#L19"><strong>Error Handler</strong></a></li>
</ul>
</li>
</ul>
<p>You can copy the source codes from ABP or use ABP directly 😀
Lets simulate the solution in our application, this simulation is not suitable for your application it just for demonstration.</p>
<p><strong>Rest Service</strong></p>
<pre><code class="language-ts">import { HttpClient, HttpRequest } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { HttpErrorReporterService } from './http-error-reporter.service';
import { catchError, throwError } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class RestService {
  http = inject(HttpClient);
  httpErrorReporterService = inject(HttpErrorReporterService);

  request(req: HttpRequest&lt;any&gt; | { method: string, url: string; }, skipHandleError = false) {
    const { method, url } = req;
    return this.http.request(method, url).pipe(catchError((err) =&gt; {
      if (!skipHandleError) {
        this.httpErrorReporterService.reportError(err);
      }
      return throwError(() =&gt; err);
    }));
  }
}

</code></pre>
<p><strong>HttpErrorReporterService</strong></p>
<pre><code class="language-ts">import { HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HttpErrorReporterService {
  private _error$ = new Subject&lt;HttpErrorResponse&gt;();

  get error$() {
    return this._error$.asObservable();
  }

  reportError(error: HttpErrorResponse) {
    this._error$.next(error);
  }
}

</code></pre>
<p><strong>ErrorHandler</strong></p>
<pre><code class="language-ts">import { Injectable, inject } from '@angular/core';
import { HttpErrorReporterService } from './http-error-reporter.service';
import { ToastService } from './toast.service';

@Injectable({
  providedIn: 'root'
})
export class ErrorHandlerService {
  httpErrorReporterService = inject(HttpErrorReporterService);
  toastMessageService = inject(ToastService);

  constructor(){
    this.httpErrorReporterService.error$.subscribe((error) =&gt; {
      this.toastMessageService.showError(error.message);
    });
  }
}

</code></pre>
<p>Now lets make an http request to check is it working</p>
<pre><code class="language-ts">restService = inject(RestService);

getTodo() {
  this.restService.request(
    { method: 'GET', url: 'https://jsonplaceholder.typicode.com/todos/1111' },
  ).subscribe(todo =&gt; {
    this.todo = todo;
  });
}
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/http-request-7.gif" alt="http-request" /></p>
<p>Now let's pass <strong>true to the <code>skipHandleError</code> parameter</strong>, let's see if the <strong>errorHandler</strong> going to skip this error or not.</p>
<pre><code class="language-ts">restService = inject(RestService);

getTodo() {
  this.restService.request(
    { method: 'GET', url: '&lt;https://jsonplaceholder.typicode.com/todos/1111&gt;' },
    skipHandleError: true,
  ).subscribe(todo =&gt; {
    this.todo = todo;
  });
}

</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-02-12-Global-Error-Handling-in-Angular/http-request-8.gif" alt="http-request" /></p>
<h3>Conclusion</h3>
<ul>
<li>To handle synchronous errors globally, you can use <a href="https://angular.io/api/core/ErrorHandler">Error Handler</a>.</li>
<li>To handle http errors globally, you can use <a href="https://angular.io/guide/http-interceptor-use-cases">HTTP - interceptor</a>. But in this method, you won't be able to skip specific cases. I recommend you use the ABP Framework's solution.</li>
</ul>
<p>Thanks for reading, if you have any advice please share it with me in the comments.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a10b057-3ea3-953e-99b6-d0f1e99da0ac" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a10b057-3ea3-953e-99b6-d0f1e99da0ac" medium="image" />
    </item>
  </channel>
</rss>