Skip to content
Back to skills

Angular Error Handling

ASecurity

Reviews Angular application-level error handling — the frontend counterpart to dotnet-error-handling's ProblemDetails contract. Flags no global ErrorHandler for uncaught exceptions, per-component ad-hoc catchError blocks with no shared error-boundary/toast pattern, HTTP error responses not parsed against the .NET ProblemDetails shape, and no user-facing fallback UI distinguishing recoverable errors from a full application crash. Outputs findings with pilot-angular error-handling standard IDs.

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 6, 2026
developmenttypescriptgoangularexpressapifrontend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 6, 2026

npx -y skills add AgenticPawan/FullStack-Pilot --skill angular-error-handling --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Angular Error Handling?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Angular Error Handling
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/agenticpawan-angular-error-handling/badge)](https://www.skillsdirectory.com/skills/agenticpawan-angular-error-handling)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: angular-error-handling
description: Reviews Angular application-level error handling — the frontend counterpart to dotnet-error-handling's ProblemDetails contract. Flags no global ErrorHandler for uncaught exceptions, per-component ad-hoc catchError blocks with no shared error-boundary/toast pattern, HTTP error responses not parsed against the .NET ProblemDetails shape, and no user-facing fallback UI distinguishing recoverable errors from a full application crash. Outputs findings with pilot-angular error-handling standard IDs.
when_to_use: ErrorHandler, global error handler Angular, error boundary, catchError, ProblemDetails Angular, HTTP error interceptor, toast notification error, fallback UI, uncaught exception Angular, crash screen
applies_to: angular>=17
---

## Standard IDs

| ID | Severity | What it checks |
|----|----------|-----------------|
| AEH-001 | P1 | No global `ErrorHandler` registered for uncaught exceptions |
| AEH-002 | P2 | Per-component ad-hoc `catchError` with no shared error-boundary/notification pattern |
| AEH-003 | P1 | HTTP error responses not parsed against the .NET `ProblemDetails` shape |
| AEH-004 | P2 | No user-facing fallback UI distinguishing a recoverable error from a full crash |

---

## Check A — No global ErrorHandler (AEH-001)

### Detection

Check `app.config.ts`/`AppModule` providers for a custom `ErrorHandler` implementation. Without
one, an uncaught exception anywhere in the component tree (a template expression throwing,
an unguarded array access) surfaces only in the browser console — the user sees a frozen
or partially-rendered page with no indication anything went wrong.

### BAD — no global ErrorHandler, uncaught exceptions vanish into the console

```typescript
export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient(), provideRouter(routes)],
  // No ErrorHandler override — Angular's default just console.errors and moves on.
};
```

### GOOD — a global ErrorHandler that logs and surfaces a recoverable notification

```typescript
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  private readonly notifications = inject(NotificationService);
  private readonly telemetry = inject(TelemetryService);

  handleError(error: unknown): void {
    this.telemetry.trackException(error); // send to Application Insights JS SDK
    this.notifications.showError('Something went wrong. Please try again.');
  }
}

export const appConfig: ApplicationConfig = {
  providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }],
};
```

---

## Check B — Ad-hoc catchError with no shared pattern (AEH-002)

### Detection

Grep components/services for repeated `catchError(err => { /* custom toast logic */ })`
blocks that each reimplement how an HTTP failure is surfaced to the user, instead of one
shared error-normalization interceptor/service reused everywhere (this builds on
`angular-http-resilience`'s error-normalization guidance, applied consistently at the UI
layer, not just the data layer).

### BAD — every component reimplements its own error toast

```typescript
this.orderService.getOrders().pipe(
  catchError(err => {
    this.snackBar.open('Failed to load orders'); // duplicated with slightly different wording per component
    return of([]);
  })
).subscribe();
```

### GOOD — one shared error-notification service, consistent messaging

```typescript
this.orderService.getOrders().pipe(
  catchError(err => this.errorNotifier.handle(err, 'Failed to load orders'))
).subscribe();

@Injectable({ providedIn: 'root' })
export class ErrorNotifierService {
  private readonly snackBar = inject(MatSnackBar);
  handle(error: AppError, fallbackMessage: string) {
    this.snackBar.open(error.userMessage ?? fallbackMessage);
    return of(null);
  }
}
```

---

## Check C — HTTP errors not parsed against ProblemDetails (AEH-003)

### Detection

Check the HTTP error-normalization interceptor (`angular-http-resilience`) for whether it
actually parses the `.NET` API's `ProblemDetails`/`ValidationProblemDetails` response body
(established in `dotnet-error-handling` ERR-002) into a typed Angular error model, or
whether it just surfaces the raw HTTP status code with no server-provided detail.

### BAD — only the HTTP status code is used, ProblemDetails body ignored

```typescript
catchError((err: HttpErrorResponse) => {
  return throwError(() => new AppError(`Request failed with status ${err.status}`));
  // err.error actually contains a ProblemDetails body with a specific title/errors dictionary — discarded.
})
```

### GOOD — ProblemDetails body parsed into a typed error model

```typescript
interface ProblemDetails {
  title: string;
  status: number;
  errors?: Record<string, string[]>;
  correlationId?: string;
}

catchError((err: HttpErrorResponse) => {
  const problem = err.error as ProblemDetails;
  return throwError(() => new AppError(problem.title, problem.errors, problem.correlationId));
})
```

---

## Check D — No fallback UI distinguishing recoverable errors from a crash (AEH-004)

### Detection

Check whether the app has a distinct "something recoverable failed, here's a retry
button" state versus a full top-level crash screen — conflating the two means a minor
failed API call (recoverable — retry the request) looks the same to the user as an
unrecoverable rendering crash (needs a full reload).

### BAD — every error, recoverable or not, shows the same blank/frozen page

```html
@if (error()) {
  <p>Error</p>
}
```

### GOOD — distinct recoverable vs. crash states

```html
@if (loadError()) {
  <div class="inline-error">
    <p>Couldn't load orders.</p>
    <button (click)="retry()">Retry</button>
  </div>
} @else if (appCrashed()) {
  <app-crash-screen /> <!-- full-page fallback set by GlobalErrorHandler, offers a reload -->
}
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…