@anglr/error-handling

May 18, 2026 · View on GitHub

npm version Build status

@anglr/error-handling

Comprehensive Angular library for HTTP error handling, providing a unified approach to managing client errors (4xx), server errors (5xx), connection issues, and form validation errors in Angular applications. The library integrates with Angular's dependency injection, HTTP interceptors, RxJS operators, and reactive forms to deliver a complete error-handling solution.

Table of contents

Installation

Install the core package via npm:

npm install @anglr/error-handling --save

Peer dependencies

The library requires the following peer dependencies:

  • @angular/core >= 20.3.2
  • @angular/common >= 20.3.2
  • @angular/forms >= 20.3.2
  • @angular/platform-browser >= 20.3.2
  • @anglr/common >= 23.0.0
  • @jscrpt/common >= 7.0.0
  • rxjs >= 7.5.7

Optional sub-packages

# Angular Material dialog renderer for internal server errors
npm install @angular/material @angular/cdk --save

# Screenshot capture on error (browser only)
npm install html2canvas --save

# Integration with @anglr/rest
npm install @anglr/rest --save

Packages

The library is organized into multiple entry points:

Entry pointDescription
@anglr/error-handlingCore error handling (interceptors, operators, services, components)
@anglr/error-handling/rest@anglr/rest integration (decorators and middlewares)
@anglr/error-handling/materialAngular Material dialog renderer for internal server errors
@anglr/error-handling/html2canvasScreenshot capture extender using html2canvas

Getting started

Basic setup

Configure global error handling in your application configuration:

import {ApplicationConfig} from '@angular/core';
import {provideHttpClient, withInterceptors} from '@angular/common/http';
import {ANGLR_EXCEPTION_HANDLER_PROVIDER, httpServerErrorInterceptor, noConnectionInterceptor, serviceUnavailableInterceptor, httpGatewayTimeoutInterceptor, provideAnglrExceptionExtenders, errorWithUrlExtender} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        ANGLR_EXCEPTION_HANDLER_PROVIDER,
        provideHttpClient(withInterceptors(
        [
            noConnectionInterceptor,
            serviceUnavailableInterceptor,
            httpGatewayTimeoutInterceptor,
            httpServerErrorInterceptor,
        ])),
        provideAnglrExceptionExtenders(
        [
            errorWithUrlExtender,
        ]),
    ],
};

Providing notifications

The library uses injection tokens for notification services. You need to provide your own Notifications implementation from @anglr/common:

import {ApplicationConfig} from '@angular/core';
import {ERROR_HANDLING_NOTIFICATIONS, CLIENT_ERROR_NOTIFICATIONS} from '@anglr/error-handling';
import {NOTIFICATIONS} from '@anglr/common';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        {
            provide: ERROR_HANDLING_NOTIFICATIONS,
            useExisting: NOTIFICATIONS,
        },
        {
            provide: CLIENT_ERROR_NOTIFICATIONS,
            useExisting: NOTIFICATIONS,
        },
    ],
};

Global exception handler

AnglrExceptionHandler replaces Angular's default ErrorHandler and provides enhanced unhandled error handling including source map resolution, notifications, and extensibility through extenders.

Registration

import {ApplicationConfig, ValueProvider} from '@angular/core';
import {ANGLR_EXCEPTION_HANDLER_PROVIDER, AnglrExceptionHandlerOptions} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        ANGLR_EXCEPTION_HANDLER_PROVIDER,
        //either use value provider or factory provider which benefits of using DI
        <ValueProvider>
        {
            provide: AnglrExceptionHandlerOptions,
            useValue: new AnglrExceptionHandlerOptions(true, false),
        },
    ],
};

Options

The AnglrExceptionHandlerOptions class accepts:

ParameterTypeDefaultDescription
debugModebooleanfalseLogs errors to browser console with full stack traces
showAlsoAlertbooleanfalseShows browser alert() with error message (debug only)

How it works

  1. Captures unhandled errors via Angular's ErrorHandler interface
  2. Resolves source-mapped stack traces (browser only, via sourcemapped-stacktrace)
  3. Sends error notifications through ERROR_HANDLING_NOTIFICATIONS
  4. Runs all registered AnglrExceptionExtender functions to enrich the error
  5. Logs the enriched error via LOGGER from @anglr/common

HTTP interceptors

All interceptors are available both as functional interceptors (recommended) and as class-based providers (deprecated).

noConnectionInterceptor

Handles HTTP responses with status 0 (server offline / no connection).

import {ApplicationConfig, ValueProvider, provideHttpClient, withInterceptors} from '@angular/common/http';
import {noConnectionInterceptor, NoConnectionInterceptorOptions} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideHttpClient(withInterceptors(
        [
            noConnectionInterceptor,
        ])),
        //either use value provider or factory provider which benefits of using DI
        <ValueProvider>
        {
            provide: NoConnectionInterceptorOptions,
            useValue: new NoConnectionInterceptorOptions('Custom offline message.'),
        },
    ],
};

Default message: 'Server is offline. Try again later.'

serviceUnavailableInterceptor

Handles HTTP 503 Service Unavailable responses.

import {ApplicationConfig, ValueProvider, provideHttpClient, withInterceptors} from '@angular/common/http';
import {serviceUnavailableInterceptor, ServiceUnavailableInterceptorOptions} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideHttpClient(withInterceptors(
        [
            serviceUnavailableInterceptor,
        ])),
        //either use value provider or factory provider which benefits of using DI
        <ValueProvider>
        {
            provide: ServiceUnavailableInterceptorOptions,
            useValue: new ServiceUnavailableInterceptorOptions('Service is temporarily unavailable.'),
        },
    ],
};

Default message: 'Remote server is unavailable. Try again later.'

httpGatewayTimeoutInterceptor

Handles HTTP 504 Gateway Timeout responses.

import {ApplicationConfig, ValueProvider, provideHttpClient, withInterceptors} from '@angular/common/http';
import {httpGatewayTimeoutInterceptor, HttpGatewayTimeoutInterceptorOptions} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideHttpClient(withInterceptors(
        [
            httpGatewayTimeoutInterceptor,
        ])),
        //either use value provider or factory provider which benefits of using DI
        <ValueProvider>
        {
            provide: HttpGatewayTimeoutInterceptorOptions,
            useValue: new HttpGatewayTimeoutInterceptorOptions('Gateway timeout occurred.'),
        },
    ],
};

Default message: 'Server did not respond in defined time.'

httpServerErrorInterceptor

Handles HTTP 5xx server errors. In dev mode (jsDevMode), logs errors and optionally renders error details through InternalServerErrorService.

import {ApplicationConfig, provideHttpClient, withInterceptors} from '@angular/common/http';
import {httpServerErrorInterceptor} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideHttpClient(withInterceptors(
        [
            httpServerErrorInterceptor,
        ])),
    ],
};

RxJS operators

processHttpClientErrorResponse

Converts HttpErrorResponse with status codes 400..499 into HttpClientError objects. Non-HTTP errors and client-side errors are re-thrown unchanged.

import {inject, Injector} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {processHttpClientErrorResponse, catchHttpClientError} from '@anglr/error-handling';

@Injectable({providedIn: 'root'})
export class UserService
{
    private _httpClient: HttpClient = inject(HttpClient);

    private _injector: Injector = inject(Injector);

    public getUser(id: number)
    {
        return this._httpClient.get(`/api/users/${id}`)
            .pipe(
                processHttpClientErrorResponse({injector: this._injector}),
                catchHttpClientError({injector: this._injector}),
            );
    }
}

Options

// With custom options
processHttpClientErrorResponse(
{
    injector: angularInjector,
    ignoredHttpStatusCodes: [401, 403, 409],
    clientErrorsResponseMapper: err => [err?.error?.message ?? 'Unknown error'],
    clientValidationErrorsResponseMapper: err => err?.error?.validationErrors ?? null,
});

catchHttpClientError

Catches HttpClientError objects (produced by processHttpClientErrorResponse) and handles them according to provided options — displaying notifications, storing validation errors, and applying behavior.

// Suppress errors (default) — observable never completes on error
catchHttpClientError({injector: angularInjector});

// Pass through — HttpClientError is emitted as next value
catchHttpClientError({injector: angularInjector, behavior: CatchHttpClientErrorBehavior.PassThrogh});

// Throw — HttpClientError is re-thrown as observable error
catchHttpClientError({injector: angularInjector, behavior: CatchHttpClientErrorBehavior.Throw});

Per-status-code configuration

Using default error handlers with custom configuration for different status codes.

catchHttpClientError(
{
    configs:
    {
        404:
        {
            behavior: CatchHttpClientErrorBehavior.Throw,
            message: 'Resource not found',
            skipErrorNotifications: false,
            skipServerValidationErrors: true,
            forceCustomMessageDisplay: true,
        },
        409:
        {
            behavior: CatchHttpClientErrorBehavior.PassThrogh,
            message: 'Conflict occurred',
        },
    },
});

Custom error handlers

Using custom error handler for specified status code.

catchHttpClientError(
{
    handlers:
    {
        404: async (error: HttpClientError) =>
        {
            console.log('Custom 404 handler', error.response.url);

            return null;
        },
    },
});

CatchHttpClientErrorBehavior

Enum controlling what happens after an HTTP client error is processed:

ValueDescription
SuppressError is handled silently, observable never completes (default)
PassThroghHttpClientError is emitted as the next observable value
ThrowHttpClientError is re-thrown as an observable error

Server validation

ServerValidationService

Root-provided service for managing server-side validation errors. It stores validation errors received from HTTP responses and notifies subscribers when they change.

import {inject} from '@angular/core';
import {ServerValidationService} from '@anglr/error-handling';

@Injectable({providedIn: 'root'})
export class MyFormService
{
    private _serverValidation: ServerValidationService = inject(ServerValidationService);

    public submitForm(data: unknown)
    {
        // Clear previous validation errors before submission
        this._serverValidation.clearServerValidationErrors();
        // ... perform HTTP request
    }
}

ServerValidationValidatorDirective

Directive that integrates server-side validation errors with Angular reactive forms. Apply the serverValidation attribute to form controls to automatically display server validation errors.

<form>
    <input formControlName="email"
           serverValidation />

    <input [formControl]="username"
           serverValidation="userName" />
</form>
  • When formControlName is available value is used for obtaining name of validation property
  • If no formControlName is available, you have to specify validation property name using serverValidation

The directive automatically revalidates the form control when server validation errors change.

Internal server error display

InternalServerErrorComponent

Component that subscribes to InternalServerErrorService and collects internal server error reports for display.

<internal-server-error />

Place this component in your root application template. It listens for 5xx error events (triggered by httpServerErrorInterceptor) and renders them using the configured InternalServerErrorRenderer.

InternalServerErrorRenderer

Interface for customizing how internal server errors are displayed:

import {InternalServerErrorInfo, InternalServerErrorRenderer} from '@anglr/error-handling';

export class CustomErrorRenderer implements InternalServerErrorRenderer
{
    public show(errorInfo: InternalServerErrorInfo, deleteCallback: (errorInfo: InternalServerErrorInfo) => void): void
    {
        // Custom rendering logic
        console.log('Server error:', errorInfo.errorHtml, errorInfo.requestUrl);
        deleteCallback(errorInfo);
    }
}

Register using the provider function:

import {ApplicationConfig} from '@angular/core';
import {provideInternalServerErrorRenderer} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideInternalServerErrorRenderer(CustomErrorRenderer),
    ],
};

Exception extenders

Exception extenders enrich error objects with additional context before they are logged. They implement the AnglrExceptionExtender type:

type AnglrExceptionExtender = (injector: Injector, error: ErrorWithStack) => Promise<ErrorWithStack>;

Built-in extenders

errorWithUrlExtender

Adds the current application URL (via Angular's Location service) to the error object.

import {provideAnglrExceptionExtenders, errorWithUrlExtender} from '@anglr/error-handling';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideAnglrExceptionExtenders(
        [
            errorWithUrlExtender,
        ]),
    ],
};

Custom extenders

import {Injector} from '@angular/core';
import {AnglrExceptionExtender, ErrorWithStack} from '@anglr/error-handling';

export const errorWithTimestampExtender: AnglrExceptionExtender = (injector: Injector, error: ErrorWithStack): Promise<ErrorWithStack> =>
{
    const extended = error as ErrorWithStack & {timestamp: string};
    extended.timestamp = new Date().toISOString();

    return Promise.resolve(extended);
};

// Register
provideAnglrExceptionExtenders(
[
    errorWithUrlExtender,
    errorWithTimestampExtender,
]);

Injection tokens

TokenTypeDefaultDescription
ERROR_HANDLING_NOTIFICATIONSNotificationsNotifications service for error handling package
CLIENT_ERROR_NOTIFICATIONSNotificationsNotifications service for HTTP client error display
HTTP_CLIENT_ERROR_RESPONSE_MAPPERHttpClientErrorResponseMappererr => [err?.error?.toString()]Maps HttpErrorResponse to error messages
HTTP_CLIENT_VALIDATION_ERROR_RESPONSE_MAPPERHttpClientValidationErrorResponseMapperMaps HttpErrorResponse to validation errors
ANGLR_EXCEPTION_EXTENDERSAnglrExceptionExtender[][]Multi-token for exception extender functions
INTERNAL_SERVER_ERROR_RENDERERInternalServerErrorRendererDummyInternalServerErrorRendererRenderer for internal server error display
HTTP_IGNORED_CLIENT_ERRORSnumber[][401, 403]HTTP status codes ignored by error processing
HTTP_CLIENT_ERROR_CONFIGSHttpClientErrorConfigsPer-status-code configuration for error handling
HTTP_CLIENT_ERROR_HANDLERSHttpClientErrorHandlersPer-status-code custom error handlers

Provider functions

FunctionDescription
provideAnglrExceptionExtenders(extenders)Registers exception extender functions
provideInternalServerErrorRenderer(renderer)Registers custom internal server error renderer
provideHttpClientErrorConfigs(configs)Provides and merges per-status error configs
provideHttpClientErrorHandlers(handlers)Provides and merges per-status error handlers
provideHttpClientErrorResponseMapper(mapper)Provides custom error response mapper
provideHttpClientValidationErrorResponseMapper(mapper)Provides custom validation error response mapper

Sub-packages

@anglr/error-handling/rest

Integration with @anglr/rest library, providing decorators and middlewares for declarative REST client error handling.

Middlewares

  • CatchHttpClientErrorMiddleware — wraps REST method responses with catchHttpClientError operator
  • HttpClientErrorProcessingMiddleware — wraps REST method responses with processHttpClientErrorResponse operator

Injection tokens

  • ERROR_HANDLING_REST_MIDDLEWARES_ORDER - definition of array of rest middlewares order including error handling middleware
  • REST_ERROR_HANDLING_MIDDLEWARE_ORDER - provider for rest middleware order with error handling middleware

Decorators

All decorators modify REST method descriptors and are used on @anglr/rest service methods:

import {RESTClient, GET, BaseUrl} from '@anglr/rest';
import {HttpClientErrorBehavior, HttpClientErrorMessages, HttpClientErrorSkipErrorNotifications, IgnoredHttpErrorStatusCodes} from '@anglr/error-handling/rest';
import {CatchHttpClientErrorBehavior} from '@anglr/error-handling';
import {NEVER} from 'rxjs';

@Injectable({providedIn: 'root'})
@BaseUrl('/api')
export class UsersRestService extends RESTClient
{
    @GET('/users/{id}')
    @HttpClientErrorBehavior(CatchHttpClientErrorBehavior.Throw)
    @HttpClientErrorMessages({404: 'User not found'})
    public getUser(@Path('id') id: number): Observable<User>
    {
        return NEVER;
    }

    @GET('/users')
    @HttpClientErrorBehavior(CatchHttpClientErrorBehavior.Suppress, 404)
    @HttpClientErrorSkipErrorNotifications()
    @IgnoredHttpErrorStatusCodes([409])
    public getUsers(): Observable<User[]>
    {
        return NEVER;
    }
}
DecoratorDescription
@HttpClientErrorBehavior(behavior, statusCode?)Sets error behavior globally or per status code
@HttpClientErrorMessages(messages)Sets custom error messages per status code
@HttpClientErrorHandlers(handlers)Sets custom error handlers per status code
@HttpClientErrorForceCustomMessage(indication?, statusCode?)Forces custom message display
@HttpClientErrorSkipErrorNotifications(indication?, statusCode?)Skips error notification display
@HttpClientErrorSkipServerValidationErrors(indication?, statusCode?)Skips server validation error processing
@HttpClientErrorsMapper(mapper)Sets custom error response mapper
@HttpClientValidationErrorsMapper(mapper)Sets custom validation error response mapper
@IgnoredHttpErrorStatusCodes(statusCodes)Sets ignored HTTP status codes

@anglr/error-handling/material

Provides Angular Material–based renderer for internal server errors using MatDialog.

Setup

import {provideInternalServerErrorRenderer} from '@anglr/error-handling';
import {DialogInternalServerErrorRenderer} from '@anglr/error-handling/material';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideInternalServerErrorRenderer(DialogInternalServerErrorRenderer),
    ],
};

The DialogInternalServerErrorRenderer opens a MatDialog at 90vw × 90vh displaying the full server error response HTML.

@anglr/error-handling/html2canvas

Provides an exception extender that captures a screenshot of the current application state when an error occurs (browser only).

Setup

import {provideAnglrExceptionExtenders, errorWithUrlExtender} from '@anglr/error-handling';
import {errorWithScreenShotExtender} from '@anglr/error-handling/html2canvas';

export const appConfig: ApplicationConfig =
{
    providers:
    [
        provideAnglrExceptionExtenders(
        [
            errorWithUrlExtender,
            errorWithScreenShotExtender,
        ]),
    ],
};

The errorWithScreenShotExtender uses html2canvas to render document.body as a PNG and attaches the base64-encoded image to the error object as screenshotBase64.

API reference

Classes

ClassDescription
HttpClientErrorNormalized wrapper for HTTP 4xx errors with errors, validationErrors, statusCode, message, response
HttpNotFoundErrorSpecialized HttpClientError for HTTP 404 responses
InternalServerErrorInfoModel for internal server error display with id, errorHtml, requestUrl
AnglrExceptionHandlerOptionsConfiguration options for the global exception handler
NoConnectionInterceptorOptionsConfiguration for noConnectionInterceptor
ServiceUnavailableInterceptorOptionsConfiguration for serviceUnavailableInterceptor
HttpGatewayTimeoutInterceptorOptionsConfiguration for httpGatewayTimeoutInterceptor

Services

ServiceProvided inDescription
AnglrExceptionHandlervia ANGLR_EXCEPTION_HANDLER_PROVIDERGlobal exception handler with source map support
InternalServerErrorServicerootEmits internal server error events for display
ServerValidationServicerootManages server-side validation errors
DummyInternalServerErrorRendererroot (default)No-op fallback renderer for internal server errors

Interfaces

InterfaceDescription
AnglrExceptionExtenderAsync function signature for extending error objects
AngularErrorAngular error shape with optional promise and rejection
CatchHttpClientErrorOptionsOptions for catchHttpClientError operator
CatchHttpClientErrorHttpStatusCodeOptionsPer-status-code config (behavior, message, notification/validation skipping)
ErrorWithStackError with optional stack property
ErrorWithUrlExtends error with optional applicationUrl
HttpClientErrorHandlerAsync handler returning processed error or null
HttpClientErrorOptionsOptions for processHttpClientErrorResponse operator
HttpClientErrorsCombined {errors, validationErrors} result
HttpClientPropertyValidationErrorMap of validation error keys to messages
HttpClientValidationErrorsProperty name to validation error map
InternalServerErrorRendererContract for rendering internal server errors

Types

TypeDescription
HttpClientErrorResponseMapper(err: HttpErrorResponse) => PromiseOr<string[]>
HttpClientValidationErrorResponseMapper(err: HttpErrorResponse) => PromiseOr<HttpClientValidationErrors|null>
HttpClientErrorMessagesRecord<number, string|undefined|null>
HttpClientErrorConfigsRecord<number, CatchHttpClientErrorHttpStatusCodeOptions|undefined|null>
HttpClientErrorHandlersRecord<number, HttpClientErrorHandler<HttpClientError>|undefined|null>

License

MIT