# Error handling

## Error handling

Lets take a look again at the previous example of authorization middleware.

{% tabs %}
{% tab title="auth.middleware.ts" %}

```typescript
import { HttpError, HttpStatus } from '@marblejs/core';

const authorize$: HttpMiddlewareEffect = req$ =>
  req$.pipe(
    switchMap(req => iif(
      () => !isAuthorized(req),
      throwError(new HttpError('Unauthorized', HttpStatus.UNAUTHORIZED)),
      of(req),
    )),
  );
```

{% endtab %}
{% endtabs %}

*Marble.js comes with a dedicated `HttpError`* class for defining request related errors that can be caught easily via error middleware. Using the *RxJS* built-in `throwError` method, we can throw an error and catch it on an upper level (e.g. directly inside *Effect* or *ErrorEffect*).

The `HttpError` class resides in the `@marblejs/core` package. The constructor takes as a first parameter an error message and as a second parameter a `HttpStatus` code that can be a plain *JavaScript* `number` or *TypeScript* enum type that can also be imported via core package. Optionally you can pass the third argument, which can contain any other error related values.

```typescript
new HttpError('Forbidden', HttpStatus.FORBIDDEN, { resource: 'index.html' });
```

## 404 error handling

*404 (Not Found)* responses are not the result of an error, so the error handler will not capture them. This behavior is because a *404* response simply indicates the absence of matched *Effect* in request lifecycle; in other words, request didn't find a proper route. All you need to do is to define a dedicated *Effect* at the very end of the effects stack to handle a 404 response.

```typescript
const notFound$ = r.pipe(
  r.matchPath('*'),
  r.matchType('*'),
  r.useEffect(req$ => req$.pipe(
    mergeMap(() =>
      throwError(new HttpError('Route not found', HttpStatus.NOT_FOUND))
    )
  )));
```

The *HttpEffect* above handles **all** paths and **all** method types *\*\**&#x61;nd throws an 404 error code that can be intercepted via *HttpErrorEffect*.

`notFound$` *Effects* can be placed in any layer you want, eg. you can have multiple *Effects* that will handle missing routes in dedicated organization levels of your API structure.

## Custom error handling effect

By default *Marble.js* comes with simple and lightweight error handling *Effect*. Because middlewares and *Effects* are based on the same generic interface, your error handlers can work very similar.

{% tabs %}
{% tab title="error.middleware.ts" %}

```typescript
const customError$: HttpErrorEffect<ThrownError> = (req$, res, meta) =>
  req$.pipe(
    mapTo(meta.error),
    map(error => ({
     status: error.status
     body: error.data
    }),
  );
```

{% endtab %}
{% endtabs %}

As any other *Effect*, error handler maps the stream of errored requests to objects of type *HttpEffectResponse* (`status`, `body`, `headers`). The *HttpErrorEffect* can retrieve from the third argument an intercepted error object which can be used for error handling-related logic.

To connect the custom error handler, all you need to do is to attach it to `error$` property in `httpListener` config object.

{% tabs %}
{% tab title="http.listener.ts" %}

```typescript
httpListener({
  middlewares,
  effects,
  // Custom error effect 👇
  error$: customError$,
});
```

{% endtab %}
{% endtabs %}
