# Errors

> VimineError — one error type for everything the API and the SDK can refuse, with a stable code.

URL: https://developers.vimine.network/en/sdk/errors/

```js
import { VimineError } from '@vimine/sdk';   // also from /server
```

Everything that goes wrong arrives as a `VimineError`, a subclass of `Error`. **`code`** is the stable
identifier to branch on: the `code` of a problem+json document (RFC 9457), the `error` of an OAuth response,
or one of the SDK's own codes.

## Properties

| | Type | |
|---|---|---|
| `code` | `string` | the stable code |
| `message` | `string` | the problem's `detail` or `title`, or `error_description` |
| `status` | `number \| null` | the HTTP status, `null` for local errors |
| `requestId` | `string \| null` | the response's `request_id`: quote it in reports |
| `detail` | `string \| null` | the problem's `detail` |
| `errors` | `FieldError[]` — `{ field?, code?, message? }` | the details of `validation_failed` and of `identification_required`; a `codicefiscale_mismatch` entry also carries `mismatches`, `hints` and `confirmable` ([guide](https://developers.vimine.network/en/guides/members-without-cf/#a-code-that-disagrees-and-the-confirmation)) |
| `cause` | `unknown` | the underlying error (`network`, `framed`) |
| `isAuthError` | `boolean` | `true` for "the session is gone: sign in again" (401, `invalid_token`, `token_expired`, `missing_token`, `invalid_grant`, `not_signed_in`) |

## The SDK's codes

| `code` | When |
|---|---|
| `invalid_options` | constructor without `clientId`, `redirectUri` or `clientSecret` |
| `network` | the request did not reach the API (`cause` carries the original error) |
| `not_signed_in` | no session, or no refresh token, for an authenticated call |
| `no_flow` | a return without a sign-in started from this browser (storage empty or expired) |
| `state_mismatch` | the return does not match the sign-in that was started |
| `framed` | `signIn()` from a cross-origin frame |
| `http_<status>` | an error response without a recognisable JSON body |

The **API** codes (`insufficient_scope`, `not_found`, `validation_failed`, `statuto_required`, `rate_limited`,
…) and the **OAuth** ones (`invalid_grant`, `access_denied`, `unauthorized_client`, …) are in
[Permissions, errors and limits](https://developers.vimine.network/en/guides/scopes-and-errors/).

## Handling them

```js
import { VimineError } from '@vimine/sdk';

try {
    await vimine.membership.acceptStatuto({ version });
} catch (err) {
    if (!(err instanceof VimineError)) throw err;
    if (err.isAuthError) return vimine.signIn({ returnTo: location.pathname });
    switch (err.code) {
        case 'statuto_outdated':  return alert(`A newer version is in force: ${err.detail}`);
        case 'insufficient_scope': return vimine.signIn({ scopes: ['statuto:accept'], prompt: 'consent' });
        case 'rate_limited':      return setTimeout(retry, 5000);
        default:                  console.error(err.code, err.requestId);
    }
}
```
