> ## 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.

# Erreurs

> Gérez SquareCloudAPIError dans squarecloud-api : statut, code et message, les codes propres au SDK, les codes de l'API par groupe, les nouvelles tentatives, les timeouts et les limites de débit.

Chaque échec de l'API ou du réseau lève une seule exception : `SquareCloudAPIError`.

```python theme={"system"}
from squarecloud import SquareCloudAPIError

try:
    client.apps.start(app_id)
except SquareCloudAPIError as error:
    print(error.status, error.code, error.message)
    print(error.method, error.path)  # "POST" "/v2/apps/<id>/start"
    print(error)  # POST /v2/apps/<id>/start: HTTP 404 APP_NOT_FOUND
```

## `SquareCloudAPIError`

`SquareCloudAPIError` est une sous-classe d'`Exception`.

| Attribut  | Type                    | Description                                                                                          |
| --------- | ----------------------- | ---------------------------------------------------------------------------------------------------- |
| `status`  | `int`                   | Statut HTTP. `0` lorsqu'aucune réponse n'est arrivée (erreur réseau, timeout, vérification locale)   |
| `code`    | `str`                   | Le code d'erreur de l'API, par ex. `APP_NOT_FOUND`, ou l'un des codes du SDK                         |
| `message` | `str`                   | L'explication du serveur. `''` lorsque le serveur n'a envoyé qu'un code                              |
| `method`  | `str`                   | Méthode HTTP de l'appel échoué                                                                       |
| `path`    | `str`                   | Chemin de l'URL de l'appel échoué, sans la chaîne de requête                                         |
| `cause`   | `BaseException \| None` | L'exception d'origine, pour `NETWORK_ERROR`, `TIMEOUT` et un JSON invalide (la même que `__cause__`) |

`str(error)` vaut `<METHOD> <path>: HTTP <status> <CODE>: <message>`, sans `HTTP <status>` lorsque le statut est `0` et sans `: <message>` lorsque le message est vide.

Deux échecs ne sont pas encapsulés :

* Une clé API vide ou composée uniquement d'espaces lève une `ValueError` dans le constructeur du client.
* Les problèmes de fichiers locaux lèvent une `OSError` : un chemin d'envoi qui ne peut pas être ouvert, un fichier qui devient illisible pendant l'envoi, ou une destination de `download_snapshot` impossible à écrire.

## Codes du SDK

| Statut | Code             | Quand                                                                                                                                                                                                                                    |
| ------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0      | `NETWORK_ERROR`  | Aucune réponse (DNS, connexion réinitialisée, corps tronqué). L'exception d'origine se trouve dans `cause`                                                                                                                               |
| 0      | `TIMEOUT`        | Une opération de socket a dépassé le [timeout](/fr/sdks/py/client#timeouts)                                                                                                                                                              |
| 0      | `FILE_TOO_LARGE` | Vérification locale : un envoi de plus de 100 Mo ou un `files.write` de plus de 10 Mo. Rien n'a été envoyé                                                                                                                               |
| 0      | `INVALID_ID`     | Vérification locale : un identifiant vide, `.` ou `..`. Rien n'a été envoyé                                                                                                                                                              |
| tous   | `UNKNOWN_ERROR`  | Une réponse sans code (comme une page d'erreur de proxy), avec le vrai `status` et le message du serveur, ou `HTTP <status>` s'il n'y en a pas. Un corps 2xx qui n'est pas du JSON a le message `Invalid JSON in HTTP <status> response` |

## Les codes sont des chaînes

`code` est une simple `str` : le SDK n'a pas d'enum de codes. La docstring de `SquareCloudAPIError` liste tous les codes connus de l'API, et les groupes ci-dessous les listent aussi.

La liste des codes de l'API s'allonge. **Traitez un code inconnu d'après son statut HTTP** :

```python theme={"system"}
def start(app_id: str):
    try:
        client.apps.start(app_id)
    except SquareCloudAPIError as error:
        match error.code:
            case "APP_NOT_FOUND":
                return None
            case "CONTAINER_ALREADY_STARTED":
                return  # fine
            case _:
                if error.status == 429:
                    return retry_later()
                if error.status >= 500:
                    return report_outage(error)
                raise
```

## Erreurs de n'importe quel appel

| Statut | Code                    | Quand                                                                                                                         |
| ------ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| 401    | `ACCESS_DENIED`         | Clé API manquante, inconnue, révoquée ou expirée                                                                              |
| 403    | `MISSING_SCOPE`         | Il manque à la clé le scope de cet appel. `message` le nomme                                                                  |
| 403    | `RESOURCE_NOT_ALLOWED`  | La clé est limitée à d'autres applications ou bases de données                                                                |
| 403    | `PERMISSION_DENIED`     | Votre rôle dans le workspace n'autorise pas l'action                                                                          |
| 404    | `ROUTE_NOT_FOUND`       | Route inconnue                                                                                                                |
| 429    | `RATE_LIMITED`          | Blocage du compte, de la clé ou de l'IP (peut durer environ 30 min), et limite des endpoints réseau et de `account.snapshots` |
| 429    | `KEEP_CALM`             | Trop rapide pour cette route                                                                                                  |
| 500    | `INTERNAL_SERVER_ERROR` | Erreur du serveur                                                                                                             |
| 503    | `DATABASE_UNAVAILABLE`  | La base de données de la plateforme est indisponible. Une mutation a peut-être déjà été appliquée                             |

## Codes de l'API par groupe

<AccordionGroup>
  <Accordion title="Introuvable">
    `APP_NOT_FOUND`, `DATABASE_NOT_FOUND`, `WORKSPACE_NOT_FOUND`, `MEMBER_NOT_FOUND`, `FILE_NOT_FOUND`, `SNAPSHOT_NOT_FOUND`, `REPOSITORY_NOT_FOUND`, `BRANCH_NOT_FOUND`, `ROUTE_NOT_FOUND`
  </Accordion>

  <Accordion title="Validation">
    `INVALID_ACCESS_TOKEN`, `INVALID_AUTORESTART`, `INVALID_BRANCH_LENGTH`, `INVALID_CODE`, `INVALID_CONTENT`, `INVALID_CONTENT_TYPE`, `INVALID_DATABASE_TYPE`, `INVALID_DATABASE_VERSION`, `INVALID_DESCRIPTION`, `INVALID_DISPLAY_NAME`, `INVALID_DOMAIN`, `INVALID_ENCODING`, `INVALID_ENV_CONTENT`, `INVALID_FILE`, `INVALID_FILENAME`, `INVALID_FILTER`, `INVALID_GROUP`, `INVALID_ID`, `INVALID_INPUT`, `INVALID_JSON_BODY`, `INVALID_MEMORY`, `INVALID_NAME`, `INVALID_PARAMETERS`, `INVALID_PATH`, `INVALID_RESET_TYPE`, `INVALID_SCOPE`, `INVALID_SNAPSHOT_ID`, `INVALID_SUBDOMAIN`, `INVALID_TIME_RANGE`, `INVALID_VERSION_ID`, `MISSING_PARAMETERS`, `MISSING_REQUIRED_FIELDS`, `NO_UPDATE_DATA`, `VALIDATION_FAILED`, `VALIDATION_TIMEOUT`, `ENV_NAME_TOO_LONG`, `ENV_CONTENT_TOO_LONG`, `TOO_MANY_ENV_VARS`, `RESERVED_DOMAIN`, `CANNOT_SET_SUBDOMAIN`, `STATIC_APP_ENV_NOT_SUPPORTED`
  </Accordion>

  <Accordion title="Authentification et permissions">
    `ACCESS_DENIED`, `MISSING_SCOPE`, `RESOURCE_NOT_ALLOWED`, `PERMISSION_DENIED`, `SCOPE_NOT_GRANTABLE`, `BLOCKED_PATH`, `UPGRADE_REQUIRED`
  </Accordion>

  <Accordion title="Limites et limites de débit">
    `RATE_LIMITED`, `KEEP_CALM`, `APPLICATIONS_LIMIT_REACHED`, `WORKSPACE_LIMIT_REACHED`, `MEMBERS_LIMIT_REACHED`, `LOAD_BALANCER_LIMIT_REACHED`, `DAILY_SNAPSHOTS_LIMIT_REACHED`, `INSUFFICIENT_MEMORY`, `FILE_TOO_LARGE`, `PAYLOAD_TOO_LARGE`, `REALTIME_MAX_CONNECTIONS`, `REALTIME_MAX_CONNECTIONS_APP`, `AI_DAILY_LIMIT_REACHED`, `AI_MAX_CONCURRENT_STREAMS`, `AI_NO_PLAN_LIMIT_REACHED`
  </Accordion>

  <Accordion title="Conteneurs (démarrage, arrêt, redémarrage)">
    `CONTAINER_ALREADY_STARTED`, `CONTAINER_ALREADY_STOPPED`, `CONTAINER_TEMPORARILY_SUSPENDED`, `CONTAINER_NOT_FOUND`, `CONTAINER_INSUFFICIENT_DISK_SPACE`, `CONTAINER_NETWORK_CONFLICT`, `ACTION_FAILED`, `DATABASE_NOT_RUNNING`
  </Accordion>

  <Accordion title="Envois, fichiers et commits">
    `UPLOAD_BUSY`, `UPLOAD_FAILED`, `UPLOAD_ABORTED`, `STORAGE_UPLOAD_FAILED`, `COMMIT_FAILED`, `READ_FAILED`, `SAVE_FAILED`, `RENAME_FAILED`, `DELETE_FAILED`, `REQUEST_ABORTED`, `EMPTY_RESPONSE`
  </Accordion>

  <Accordion title="Snapshots">
    `SNAPSHOT_FAILED`, `SNAPSHOT_PROCESSING`, `SNAPSHOT_RESTORE_FAILED`, `SNAPSHOT_DATABASE_MISMATCH`, `RESTORE_IN_PROGRESS`
  </Accordion>

  <Accordion title="Deploys et GitHub">
    `GIT_ALREADY_CONFIGURED`, `GIT_NOT_CONFIGURED`, `GITHUB_NOT_CONNECTED`, `REPOSITORY_BRANCH_ALREADY_CONFIGURED`, `REPOSITORY_NOT_AVAILABLE`, `REPOSITORY_PERMISSION_REQUIRED`, `FAILED_TO_FETCH`
  </Accordion>

  <Accordion title="Réseau et domaines">
    `ANALYTICS_BUSY`, `UNABLE_TO_FETCH_ANALYTICS`, `UNABLE_TO_FETCH_ERRORS`, `UNABLE_TO_FETCH_PERFORMANCE`, `DNS_FAILED`, `DOMAIN_ALREADY_EXISTS`, `NO_CUSTOM_DOMAIN`, `PURGE_CACHE_FAILED`, `LOGS_UNAVAILABLE`, `METRICS_NOT_SUPPORTED`
  </Accordion>

  <Accordion title="Bases de données et workspaces">
    `DATABASE_CREATION_FAILED`, `DATABASE_UNAVAILABLE`, `RESET_FAILED`, `WORKSPACE_CREATION_FAILED`, `APP_ALREADY_IN_WORKSPACE`, `MEMBER_ALREADY_ADDED`, `CANNOT_EDIT_OWNER`, `CANNOT_INVITE_OWNER`, `CANNOT_LEAVE_OWNER`, `CONFLICTING_RESOURCES`
  </Accordion>

  <Accordion title="Plateforme">
    `INTERNAL_SERVER_ERROR`, `CLUSTER_MAINTENANCE_TRY_LATER`, `CLUSTER_SELECTION_FAILED`, `CLUSTER_TIMEOUT`, `CLUSTER_UNAVAILABLE`, `AI_UNAVAILABLE`
  </Accordion>

  <Accordion title="Dépréciés">
    `RATE_LIMIT` et `RATE_LIMIT_EXCEEDED` figurent toujours dans la liste, marqués comme dépréciés : l'API répond désormais `RATE_LIMITED` pour les deux.
  </Accordion>
</AccordionGroup>

Les erreurs de `ai.chat()` utilisent plutôt les codes OpenAI en minuscules (`access_denied`, `rate_limit_exceeded`, `server_overloaded`, ...). Voir [IA](/fr/sdks/py/ai#erreurs).

## Nouvelles tentatives

Le SDK ne réessaie que ce qui peut être répété sans risque, jusqu'à `max_retries` fois (par défaut `2`, soit jusqu'à 3 tentatives) :

| Réessayé                   | Méthodes         |
| -------------------------- | ---------------- |
| `NETWORK_ERROR`            | `GET` uniquement |
| 503 `UPLOAD_BUSY`          | Toute méthode    |
| 503 `ANALYTICS_BUSY`       | Toute méthode    |
| 503 `DATABASE_UNAVAILABLE` | `GET` uniquement |

Il ne réessaie **jamais** :

* `TIMEOUT` ;
* aucun **429** : `RATE_LIMITED` peut être un blocage d'environ 30 minutes, et `KEEP_CALM` n'est pas réessayé non plus ;
* les autres 5xx ;
* les erreurs d'IA.

503 `DATABASE_UNAVAILABLE` peut arriver alors qu'une mutation a déjà été appliquée : le SDK ne la réessaie donc pas en dehors de `GET`. Réessayez vous-même vos mutations idempotentes si nécessaire.

L'attente avant la nouvelle tentative `n` (à partir de 0) est `min(8 s, 500 ms · 2^n) · U(0.5, 1)` : un backoff exponentiel avec un jitter de 50 % à 100 %. Définissez `max_retries=0` pour désactiver les nouvelles tentatives.

## Timeouts

`timeout` (30 s) s'applique **par opération de socket** (la connexion et chaque lecture ou écriture), et non à toute la requête. Voir [Timeouts](/fr/sdks/py/client#timeouts) pour les appels avec un plancher de 120 s et les appels sans timeout. Un timeout lève `TIMEOUT` avec le statut `0` et n'est jamais réessayé.

## Limites de débit

Chaque compte dispose d'une limite de requêtes par 60 secondes, fixée par son plan ([valeurs](/fr/api-reference/limitations-and-restrictions)), et certaines routes ont la leur :

* **429 `RATE_LIMITED`** : un blocage du compte, de la clé API ou de l'IP, qui peut durer environ 30 minutes. C'est aussi la limite des endpoints réseau et de `account.snapshots`.
* **429 `KEEP_CALM`** : trop d'appels vers une même route en peu de temps.

Le SDK ne réessaie jamais un 429. Ralentissez, et attendez avant de réessayer.
