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

# Fehler

> Behandle SquareCloudAPIError in squarecloud-api: Status, Code und Nachricht, die eigenen Codes des SDK, die API-Codes nach Gruppen, Wiederholungen, Timeouts und Rate Limits.

Jeder API- und Netzwerkfehler wirft eine einzige 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` ist eine Unterklasse von `Exception`.

| Attribut  | Typ                     | Beschreibung                                                                                               |
| --------- | ----------------------- | ---------------------------------------------------------------------------------------------------------- |
| `status`  | `int`                   | HTTP-Status. `0`, wenn keine Antwort eingetroffen ist (Netzwerkfehler, Timeout, lokale Prüfung)            |
| `code`    | `str`                   | Der Fehlercode der API, z. B. `APP_NOT_FOUND`, oder einer der Codes des SDK                                |
| `message` | `str`                   | Die Erklärung des Servers. `''`, wenn der Server nur einen Code gesendet hat                               |
| `method`  | `str`                   | HTTP-Methode des fehlgeschlagenen Aufrufs                                                                  |
| `path`    | `str`                   | URL-Pfad des fehlgeschlagenen Aufrufs, ohne den Query-String                                               |
| `cause`   | `BaseException \| None` | Die ursprüngliche Exception, bei `NETWORK_ERROR`, `TIMEOUT` und ungültigem JSON (dieselbe wie `__cause__`) |

`str(error)` lautet `<METHOD> <path>: HTTP <status> <CODE>: <message>`, ohne `HTTP <status>`, wenn der Status `0` ist, und ohne `: <message>`, wenn die Nachricht leer ist.

Zwei Fehler werden nicht verpackt:

* Ein leerer oder nur aus Leerzeichen bestehender API-Schlüssel wirft im Konstruktor des Clients einen `ValueError`.
* Lokale Dateiprobleme werfen einen `OSError`: ein Upload-Pfad, der sich nicht öffnen lässt, eine Datei, die während des Uploads unlesbar wird, oder ein Ziel von `download_snapshot`, das sich nicht schreiben lässt.

## Codes des SDK

| Status   | Code             | Wann                                                                                                                                                                                                                                                    |
| -------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0        | `NETWORK_ERROR`  | Keine Antwort (DNS, Verbindung zurückgesetzt, Body abgeschnitten). Die ursprüngliche Exception steht in `cause`                                                                                                                                         |
| 0        | `TIMEOUT`        | Eine Socket-Operation hat das [Timeout](/de/sdks/py/client#timeouts) überschritten                                                                                                                                                                      |
| 0        | `FILE_TOO_LARGE` | Lokale Prüfung: ein Upload über 100 MB oder ein `files.write` über 10 MB. Es wurde nichts gesendet                                                                                                                                                      |
| 0        | `INVALID_ID`     | Lokale Prüfung: eine ID, die leer, `.` oder `..` ist. Es wurde nichts gesendet                                                                                                                                                                          |
| beliebig | `UNKNOWN_ERROR`  | Eine Antwort ohne Code (etwa die Fehlerseite eines Proxys), mit dem echten `status` und der Nachricht des Servers oder `HTTP <status>`, wenn es keine gibt. Ein 2xx-Body, der kein JSON ist, hat die Nachricht `Invalid JSON in HTTP <status> response` |

## Codes sind Strings

`code` ist ein einfacher `str`: Das SDK hat kein Enum für Codes. Der Docstring von `SquareCloudAPIError` listet jeden bekannten API-Code auf, und die Gruppen weiter unten ebenfalls.

Die Liste der API-Codes wächst. **Behandle einen unbekannten Code anhand seines HTTP-Status**:

```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
```

## Fehler bei jedem Aufruf

| Status | Code                    | Wann                                                                                                                              |
| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 401    | `ACCESS_DENIED`         | Fehlender, unbekannter, widerrufener oder abgelaufener API-Schlüssel                                                              |
| 403    | `MISSING_SCOPE`         | Dem Schlüssel fehlt der Scope dieses Aufrufs. `message` nennt ihn                                                                 |
| 403    | `RESOURCE_NOT_ALLOWED`  | Der Schlüssel ist auf andere Apps oder Datenbanken beschränkt                                                                     |
| 403    | `PERMISSION_DENIED`     | Deine Workspace-Rolle erlaubt die Aktion nicht                                                                                    |
| 404    | `ROUTE_NOT_FOUND`       | Unbekannte Route                                                                                                                  |
| 429    | `RATE_LIMITED`          | Sperre von Konto, Schlüssel oder IP (kann etwa 30 Min. dauern) sowie das Limit der Netzwerk-Endpoints und von `account.snapshots` |
| 429    | `KEEP_CALM`             | Zu schnell für diese Route                                                                                                        |
| 500    | `INTERNAL_SERVER_ERROR` | Serverfehler                                                                                                                      |
| 503    | `DATABASE_UNAVAILABLE`  | Die Datenbank der Plattform ist nicht verfügbar. Eine Mutation wurde möglicherweise bereits angewendet                            |

## API-Codes nach Gruppen

<AccordionGroup>
  <Accordion title="Nicht gefunden">
    `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="Validierung">
    `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="Authentifizierung und Berechtigungen">
    `ACCESS_DENIED`, `MISSING_SCOPE`, `RESOURCE_NOT_ALLOWED`, `PERMISSION_DENIED`, `SCOPE_NOT_GRANTABLE`, `BLOCKED_PATH`, `UPGRADE_REQUIRED`
  </Accordion>

  <Accordion title="Limits und Rate Limits">
    `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="Container (Starten, Stoppen, Neustarten)">
    `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="Uploads, Dateien und 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 und 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="Netzwerk und Domains">
    `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="Datenbanken und 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="Plattform">
    `INTERNAL_SERVER_ERROR`, `CLUSTER_MAINTENANCE_TRY_LATER`, `CLUSTER_SELECTION_FAILED`, `CLUSTER_TIMEOUT`, `CLUSTER_UNAVAILABLE`, `AI_UNAVAILABLE`
  </Accordion>

  <Accordion title="Veraltet">
    `RATE_LIMIT` und `RATE_LIMIT_EXCEEDED` sind weiterhin aufgeführt und als veraltet markiert: Die API antwortet jetzt in beiden Fällen mit `RATE_LIMITED`.
  </Accordion>
</AccordionGroup>

Fehler von `ai.chat()` verwenden stattdessen kleingeschriebene OpenAI-Codes (`access_denied`, `rate_limit_exceeded`, `server_overloaded`, ...). Siehe [KI](/de/sdks/py/ai#fehler).

## Wiederholungen

Das SDK wiederholt nur, was sich gefahrlos wiederholen lässt, bis zu `max_retries` Mal (Standard `2`, also bis zu 3 Versuche):

| Wiederholt                 | Methoden     |
| -------------------------- | ------------ |
| `NETWORK_ERROR`            | Nur `GET`    |
| 503 `UPLOAD_BUSY`          | Jede Methode |
| 503 `ANALYTICS_BUSY`       | Jede Methode |
| 503 `DATABASE_UNAVAILABLE` | Nur `GET`    |

**Nie** wiederholt werden:

* `TIMEOUT`;
* jedes **429**: `RATE_LIMITED` kann eine Sperre von etwa 30 Minuten sein, und auch `KEEP_CALM` wird nicht wiederholt;
* andere 5xx;
* KI-Fehler.

503 `DATABASE_UNAVAILABLE` kann eintreffen, nachdem eine Mutation bereits angewendet wurde, daher wiederholt das SDK ihn außerhalb von `GET` nicht. Wiederhole deine eigenen idempotenten Mutationen, wenn nötig.

Die Wartezeit vor Wiederholung `n` (ab 0) beträgt `min(8 s, 500 ms · 2^n) · U(0.5, 1)`: exponentielles Backoff mit 50 % bis 100 % Jitter. Setze `max_retries=0`, um Wiederholungen abzuschalten.

## Timeouts

`timeout` (30 s) gilt **pro Socket-Operation** (der Verbindungsaufbau und jedes Lesen oder Schreiben), nicht für die gesamte Anfrage. Unter [Timeouts](/de/sdks/py/client#timeouts) findest du die Aufrufe mit einem Mindestwert von 120 s und die Aufrufe ohne Timeout. Ein Timeout wirft `TIMEOUT` mit Status `0` und wird nie wiederholt.

## Rate Limits

Jedes Konto hat ein Limit an Anfragen pro 60 Sekunden, das sein Plan festlegt ([Werte](/de/api-reference/limitations-and-restrictions)), und manche Routen haben ein eigenes:

* **429 `RATE_LIMITED`**: eine Sperre des Kontos, API-Schlüssels oder der IP, die etwa 30 Minuten dauern kann. Auch das Limit der Netzwerk-Endpoints und von `account.snapshots`.
* **429 `KEEP_CALM`**: zu viele Aufrufe an eine Route in kurzer Zeit.

Das SDK wiederholt ein 429 nie. Werde langsamer und warte, bevor du es erneut versuchst.
