> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK：错误与重试

> 在 @squarecloud/api 中处理 SquareCloudAPIError：状态、代码和消息，SDK 自身的错误代码，以及重试、超时和速率限制。

所有 API 失败、网络失败和本地失败都会抛出同一个类：`SquareCloudAPIError`。

示例使用[创建客户端](/zh/sdks/js/client#创建客户端)中的 `api` 客户端。`appId` 是你的某个应用的 ID：[`api.account.me()`](/zh/sdks/js/client#账户) 会列出它们。

```typescript theme={"system"}
import { SquareCloudAPI, SquareCloudAPIError } from "@squarecloud/api";

try {
    await api.apps.start(appId);
} catch (error) {
    if (error instanceof SquareCloudAPIError) {
        console.error(error.status, error.code, error.message);
        console.error(error.method, error.path); // "POST" "/v2/apps/<id>/start"
    }
}
```

## `SquareCloudAPIError`

`SquareCloudAPIError` 继承自 `Error`（它**不是** `TypeError`）。

| 属性 | 类型 | 说明 |
| - | - | - |
| `status` | `number` | HTTP 状态。没有收到响应时为 `0`（网络错误、超时、本地检查） |
| `code` | `ErrorCode` | API 的错误代码，例如 `APP_NOT_FOUND`，或 SDK 自身的代码之一 |
| `message` | `string` | 服务器给出的说明。当服务器只发送了代码时，即为该代码本身 |
| `method` | `string` | 失败调用的 HTTP 方法 |
| `path` | `string` | 失败调用的 URL 路径，不含查询字符串 |
| `cause` | `unknown` | 原始错误，适用于 `NETWORK_ERROR` 和无效 JSON |

有两种失败不会被包装：

* 被中止的调用会以该 signal 的 `reason` 拒绝。被中止的 `realtime()` 循环会直接结束。
* 无法打开的上传路径会抛出文件系统错误。

## SDK 代码

| 状态 | 代码 | 触发条件 |
| - | - | - |
| 0 | `NETWORK_ERROR` | 没有响应（DNS、连接重置、响应体被截断）。原始错误位于 `cause` 中 |
| 0 | `TIMEOUT` | 在[超时](/zh/sdks/js/client#超时)时间内没有响应 |
| 0 | `FILE_TOO_LARGE` | 本地检查：上传超过 100 MB 或 `files.write` 超过 10 MB。未发送任何内容 |
| 0 | `INVALID_ID` | 本地检查：ID 为空、`.` 或 `..`。未发送任何内容 |
| 任意 | `UNKNOWN_ERROR` | 没有代码的响应（例如代理的错误页面），带有真实的 `status` 和消息 `HTTP <status>`。不是 JSON 的 2xx 响应体的消息为 `Invalid JSON in HTTP <status> response` |

## `ErrorCode` 类型

`ErrorCode` **仅是一个类型**（没有运行时对象）。它列出了所有公开的 API 代码、已弃用的代码以及 SDK 的代码，外加 `string & {}`，因此你的编辑器可以自动补全已知代码，而新代码仍能通过类型检查。`RATE_LIMIT` 和 `RATE_LIMIT_EXCEEDED` 仍保留在该类型中，并被标记为已弃用：API 现在对这两者都返回 `RATE_LIMITED`。

API 代码的列表会不断增加。**请根据 HTTP 状态处理未知代码**：

```typescript theme={"system"}
async function start(appId: string) {
    try {
        await api.apps.start(appId);
    } catch (error) {
        if (!(error instanceof SquareCloudAPIError)) throw error;

        switch (error.code) {
            case "APP_NOT_FOUND":
                return null;
            case "CONTAINER_ALREADY_STARTED":
                return; // fine
            default:
                if (error.status === 429) return retryLater();
                if (error.status >= 500) return reportOutage(error);
                throw error;
        }
    }
}
```

## API 错误代码

其他所有代码都来自 API。[API 错误参考](/zh/api-reference/errors)列出了每个代码及其 HTTP 状态、含义和解决方法，每个 SDK 页面也列出了其方法最常返回的代码。任何调用还可能返回 401 `ACCESS_DENIED`（密钥有误）、403 `MISSING_SCOPE` 或 `RESOURCE_NOT_ALLOWED`（[密钥的限制](/zh/sdks/js/client#api-密钥与作用域)）、429（参见[速率限制](#速率限制)）或 503 `DATABASE_UNAVAILABLE`。

`ai.chat()` 的错误则使用小写的 OpenAI 代码（`access_denied`、`rate_limit_exceeded`、`server_overloaded`……）。参见 [AI](/zh/sdks/js/ai#错误)。

## 重试

SDK 只重试可以安全重复的操作，最多 `maxRetries` 次（默认 `2`，即最多 3 次尝试）：

| 重试的情况 | 方法 |
| - | - |
| `NETWORK_ERROR` | 仅 `GET` |
| 503 `UPLOAD_BUSY` | 任意方法 |
| 503 `ANALYTICS_BUSY` | 任意方法 |
| 503 `DATABASE_UNAVAILABLE` | 仅 `GET` |

它**从不**重试：

* `TIMEOUT`；
* 任何 **429**：`RATE_LIMITED` 可能是持续约 30 分钟的封锁，`KEEP_CALM` 也不会重试；
* 其他 5xx；
* AI 错误。

503 `DATABASE_UNAVAILABLE` 可能在变更操作已被应用之后才到达，因此 SDK 不会在 `GET` 以外重试它。如有需要，请自行重试你的幂等变更操作。

第 `n` 次重试（从 0 开始）之前的等待时间为 `min(8 s, 500 ms · 2^n) · U(0.5, 1)`：带有 50% 到 100% 抖动的指数退避。设置 `maxRetries: 0` 可关闭重试。

## 超时

`timeoutMs`（30 秒）按每次尝试计算，覆盖整个响应。关于具有 120 秒下限的调用以及没有超时的调用，请参见[超时](/zh/sdks/js/client#超时)。超时会抛出状态为 `0` 的 `TIMEOUT`，且从不重试。

## 速率限制

每个账户都有每 60 秒的请求数限制，由其套餐决定（[具体数值](/zh/api-reference/limitations-and-restrictions)），部分路由还有各自的限制：

* **429 `RATE_LIMITED`**：账户或 API 密钥超出了请求配额，会被封锁约 30 分钟；或者某个 IP 持续发送无效密钥，会被短时间封锁。也是网络 endpoint 和 `account.snapshots` 的限制。
* **429 `KEEP_CALM`**：短时间内对同一路由的调用过多。

SDK 从不重试 429。请放慢速度，并在再次尝试之前等待。

## 后续步骤

<CardGroup cols={2}>
  <Card title="API 错误参考" icon="book" href="/zh/api-reference/errors">
    所有错误代码及其含义和解决方法。
  </Card>

  <Card title="限制与约束" icon="gauge" href="/zh/api-reference/limitations-and-restrictions">
    各套餐的请求限制。
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.