# 错误

> VimineError——API 和 SDK 可能拒绝的一切都使用同一种错误类型，并带有稳定的错误码。

URL: https://developers.vimine.network/zh-hans/sdk/errors/

```js
import { VimineError } from '@vimine/sdk';   // 也可从 /server 导入
```

所有出错的情况都以 `VimineError` 的形式出现，它是 `Error` 的子类。**`code`** 是用于分支判断的稳定标识：它可以是 problem+json 文档（RFC 9457）的 `code`、OAuth 响应的 `error`，或 SDK 自己的错误码之一。

## 属性

| | 类型 | |
|---|---|---|
| `code` | `string` | 稳定的错误码 |
| `message` | `string` | problem 的 `detail` 或 `title`，或 `error_description` |
| `status` | `number \| null` | HTTP 状态码，本地错误为 `null` |
| `requestId` | `string \| null` | 响应的 `request_id`：报告问题时请注明 |
| `detail` | `string \| null` | problem 的 `detail` |
| `errors` | `FieldError[]`——`{ field?, code?, message? }` | `validation_failed` 和 `identification_required` 的详细信息；`codicefiscale_mismatch` 记录还带有 `mismatches`、`hints` 和 `confirmable`（[指南](https://developers.vimine.network/zh-hans/guides/members-without-cf/#不一致的税号与确认)） |
| `cause` | `unknown` | 底层错误（`network`、`framed`） |
| `isAuthError` | `boolean` | 表示“会话已失效：请重新登录”时为 `true`（401、`invalid_token`、`token_expired`、`missing_token`、`invalid_grant`、`not_signed_in`） |

## SDK 自己的错误码

| `code` | 何时出现 |
|---|---|
| `invalid_options` | 构造函数缺少 `clientId`、`redirectUri` 或 `clientSecret` |
| `network` | 请求未能到达 API（`cause` 带有原始错误） |
| `not_signed_in` | 进行认证调用时没有会话，或没有刷新令牌 |
| `no_flow` | 收到返回，但本浏览器没有发起过登录（存储为空或已过期） |
| `state_mismatch` | 返回与发起的登录不匹配 |
| `framed` | 在跨域框架中调用了 `signIn()` |
| `http_<status>` | 错误响应没有可识别的 JSON 正文 |

**API** 错误码（`insufficient_scope`、`not_found`、`validation_failed`、`statuto_required`、`rate_limited` 等）和 **OAuth** 错误码（`invalid_grant`、`access_denied`、`unauthorized_client` 等）见[权限、错误与限制](https://developers.vimine.network/zh-hans/guides/scopes-and-errors/)。

## 处理错误

```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(`已有更新的版本生效：${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);
    }
}
```
