> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ev-cloud.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ev-cloud.ai/_mcp/server.

# Errors and retries

## Errors

A `4xx` or `5xx` response raises an error that carries the status code and the response body. Each documented status has its own class, so you can catch only what you expect.

**`TypeScript`**

```typescript TypeScript
import { EvcloudSDK, EvcloudSDKError, EvcloudSDKTypes } from "evcloud-sdk";

try {
    await client.emsp.commands.get({ tracking_id: "trk-123" });
} catch (error) {
    if (error instanceof EvcloudSDKTypes.NotFoundError) {
        // Unknown tracking id for this organization.
    } else if (error instanceof EvcloudSDKError) {
        console.error(error.statusCode, error.body);
    } else {
        throw error;
    }
}
```

**`Python`**

```python Python
from evcloud_sdk import NotFoundError
from evcloud_sdk.core.api_error import ApiError

try:
    client.emsp.commands.get("trk-123")
except NotFoundError:
    pass  # Unknown tracking id for this organization.
except ApiError as error:
    print(error.status_code, error.body)
```

| Status | TypeScript (`EvcloudSDKTypes.*`) | Python (`evcloud_sdk.*`)   |
| ------ | -------------------------------- | -------------------------- |
| 400    | `BadRequestError`                | `BadRequestError`          |
| 401    | `UnauthorizedError`              | `UnauthorizedError`        |
| 403    | `ForbiddenError`                 | `ForbiddenError`           |
| 404    | `NotFoundError`                  | `NotFoundError`            |
| 409    | `ConflictError`                  | `ConflictError`            |
| 412    | `PreconditionFailedError`        | `PreconditionFailedError`  |
| 422    | `UnprocessableEntityError`       | `UnprocessableEntityError` |
| 429    | `TooManyRequestsError`           | `TooManyRequestsError`     |
| 502    | `BadGatewayError`                | `BadGatewayError`          |
| 504    | `GatewayTimeoutError`            | `GatewayTimeoutError`      |

All of them extend `EvcloudSDKError` (TypeScript) or `ApiError` (Python), and so does any other status. A request that runs out of time raises `EvcloudSDKTimeoutError` in TypeScript and `httpx.TimeoutException` in Python.

## Retries

The SDKs retry a failed request up to **2** times, with exponential backoff, when the response is `408`, `429` or `5xx`. Change it per client (`maxRetries`) or per request (`max_retries` in Python's `request_options`).

### What is never resent

A `POST` that could act twice is sent **once**, even after a `503`. If the response was lost, the first attempt may already have created the location or sent the command, so a retry would do it again. This covers creates, commands and other actions.

Before you retry one of these yourself, check whether the first attempt went through, for example with `emsp.commands.list` or `energy.controlRequests.list`.

Operations that require an `Idempotency-Key` header, such as `emsp.tokens.provision` and the eMSP token and network actions, keep their retries: the API returns the first result for a repeated key.