# Fehler

> Jeder Fehlercode, den Ikiform zurückgibt, mit HTTP-Status, Ursache und Lösung.

Formular-Einsendungen und die REST-API teilen sich eine Fehlerhülle. JSON-Requests erhalten sie mit dem passenden HTTP-Status; Formular-Posts aus dem Browser erhalten eine gehostete Fehlerseite mit derselben Meldung und demselben Status.

## Die Fehlerhülle

`Fehler`:

```json
{
  "ok": false,
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Please slow down."
  },
  "request_id": "req_01k7v2c9t3e8m5q4x6z0a1b2c3"
}
```

- `error.code` ist stabil; verzweige danach. `error.message` ist einfaches Englisch für Menschen und kann sich ändern.
- `error.fields` ist bei Validierungsfehlern vorhanden, nach Feld-ID geschlüsselt, jeweils mit einer Liste von Meldungen. Fehler, die den ganzen Body betreffen, nutzen den Schlüssel `_form`.
- `error.challenge_url` ist bei `challenge_required` vorhanden.
- `request_id` entspricht dem Header `X-Request-Id`, den jede Antwort trägt.
- Antworten mit Rate-Limit tragen `Retry-After` in Sekunden. Beide Header sind aus Browser-Code lesbar.

## Codes

| Status | Code | Wo |
| --- | --- | --- |
| 400 | [`invalid_body`](#invalid-body) | Absenden |
| 400 | [`invalid_request`](#invalid-request) | API |
| 401 | [`unauthorized`](#unauthorized) | API |
| 402 | [`plan_required`](#plan-required) | Absenden |
| 402 | [`test_limit_reached`](#test-limit-reached) | Absenden |
| 403 | [`forbidden`](#forbidden) | Beide |
| 403 | [`origin_not_allowed`](#origin-not-allowed) | Absenden |
| 403 | [`form_paused`](#form-paused) | Absenden |
| 403 | [`captcha_failed`](#captcha-failed) | Absenden |
| 403 | [`challenge_required`](#challenge-required) | Absenden |
| 404 | [`not_found`](#not-found) | Beide |
| 405 | [`method_not_allowed`](#method-not-allowed) | API |
| 409 | [`idempotency_in_progress`](#idempotency-in-progress) | Absenden |
| 413 | [`payload_too_large`](#payload-too-large) | Absenden |
| 415 | [`unsupported_media_type`](#unsupported-media-type) | Absenden |
| 415 | [`unsupported_charset`](#unsupported-charset) | Absenden |
| 422 | [`validation_failed`](#validation-failed) | Absenden |
| 422 | [`files_not_supported`](#files-not-supported) | Absenden |
| 422 | [`too_deep`](#too-deep) | Absenden |
| 422 | [`idempotency_mismatch`](#idempotency-mismatch) | Absenden |
| 429 | [`rate_limited`](#rate-limited) | Beide |
| 429 | [`quota_exceeded`](#quota-exceeded) | Absenden |
| 500 | [`server_error`](#server-error) | Beide |

### 400 invalid_body

|   |   |
| --- | --- |
| Meldung | `The request body could not be read.` |
| Ursache | Fehlerhaftes JSON oder Multipart, ein JSON-Array oder -String statt eines Objekts, oder ein Idempotenzschlüssel mit mehr als 255 Zeichen. |
| Lösung | Sende ein einzelnes JSON-Objekt, oder lass den Browser oder `FormData` den Body bauen. |

### 400 invalid_request

|   |   |
| --- | --- |
| Meldung | `The request is invalid.` |
| Ursache | `limit`, `status`, `form_id` oder `cursor` ist ungültig. Die Meldung nennt den Parameter. |
| Lösung | Nutze `limit` 1 bis 100, `status` `received` oder `spam`, eine echte `frm_`-ID und Cursor genau so, wie sie zurückgegeben wurden. |

### 401 unauthorized

|   |   |
| --- | --- |
| Meldung | `A valid API key is required.` |
| Ursache | Kein Header `Authorization`, kein Bearer-Token, oder ein unbekannter, widerrufener oder abgelaufener Schlüssel. |
| Lösung | Sende `Authorization: Bearer ik_sk_...` mit einem gültigen Secret Key. |

### 402 plan_required

|   |   |
| --- | --- |
| Meldung | `This form isn't accepting submissions right now.` |
| Ursache | Der Workspace hat keinen aktiven Tarif. Posts von einer Live-Site werden gespeichert und 30 Tage lang zurückgehalten, bis zu 100 pro Monat, und die Meldung sagt dann, dass die Einsendung gespeichert wurde. Spam und Posts darüber hinaus werden nicht gespeichert. |
| Lösung | Wähle einen Tarif oder kauf ein Einsendungspaket unter **Settings › Plan and usage**. Zurückgehaltene Einsendungen kommen an, sobald eines davon startet. Siehe [Testen ohne Tarif](https://ikiform.com/de/docs/limits.md#testing-without-a-plan). |

### 402 test_limit_reached

|   |   |
| --- | --- |
| Meldung | `This workspace used its test submissions for this month. Pick a plan to keep sending.` |
| Ursache | Der Workspace hat keinen Tarif und diesen Monat schon 50 Test-Einsendungen von `localhost` erhalten. |
| Lösung | Wähle einen Tarif oder warte auf den nächsten Monat. „Test senden“ im Dashboard funktioniert weiterhin. |

### 403 forbidden

|   |   |
| --- | --- |
| Meldung | `You do not have access to this resource.` |
| Ursache | Der API-Schlüssel ist fehlerhaft, gehört zu einem anderen Workspace, ist bei der REST-API ein Publishable Key oder hat nicht den nötigen Scope. |
| Lösung | Nutze einen Secret Key aus diesem Workspace mit dem Scope, den die Meldung nennt. |

### 403 origin_not_allowed

|   |   |
| --- | --- |
| Meldung | `This form does not accept submissions from this site.` |
| Ursache | Der Post kam von einer Site außerhalb der erlaubten Domains des Formulars und das Formular lehnt Abweichungen ab, oder ein Publishable Key wurde von einer Domain verwendet, die nicht beim Schlüssel eingetragen ist. |
| Lösung | Füge die Site zu **Allowed domains** oder zu den Domains des Schlüssels hinzu. Für Posts vom Server nutze einen Secret Key. |

### 403 form_paused

|   |   |
| --- | --- |
| Meldung | `This form is not accepting submissions right now.` |
| Ursache | Das Formular ist im Dashboard pausiert. |
| Lösung | Setze das Formular fort. |

### 403 captcha_failed

|   |   |
| --- | --- |
| Meldung | `The captcha check failed. Please try again.` |
| Ursache | Das Turnstile-Token fehlt, ist abgelaufen, wurde schon verwendet oder konnte nicht verifiziert werden. |
| Lösung | Hol dir für jedes Absenden ein neues Token. Bei eigenen Schlüsseln prüf, ob der Site Key zum Secret passt. |

### 403 challenge_required

|   |   |
| --- | --- |
| Meldung | `Complete the human check, then send the form again.` |
| Ursache | Das Formular nutzt die Ikiform-Menschlichkeitsprüfung und ein JSON-Post kam ohne Token an. |
| Lösung | Ruf `challenge(formId)` aus dem SDK auf und übergib das Token, oder nutze `error.challenge_url`. Posts vom Server können stattdessen einen Secret Key senden. |

### 404 not_found

|   |   |
| --- | --- |
| Meldung | `Not found.` |
| Ursache | Das Formular existiert nicht, wurde gelöscht oder deaktiviert, oder die ID oder Route ist falsch. Wird auch bei einem `GET` an `/f/<formId>` zurückgegeben. |
| Lösung | Kopiere den Endpunkt aus der Übersicht des Formulars und sende per POST, statt ihn in einem Tab zu öffnen. |

### 405 method_not_allowed

|   |   |
| --- | --- |
| Meldung | `This method is not allowed here.` |
| Ursache | Ein Browser-Preflight an die REST-API, die nur von Server zu Server funktioniert. |
| Lösung | Ruf `/api/v1` aus deinem Backend auf. |

### 409 idempotency_in_progress

|   |   |
| --- | --- |
| Meldung | `A request with this idempotency key is still being processed.` |
| Ursache | Ein Request mit diesem Idempotenzschlüssel wird noch verarbeitet. |
| Lösung | Warte einen Moment und versuch es mit demselben Schlüssel erneut; du erhältst die erste Antwort. |

### 413 payload_too_large

|   |   |
| --- | --- |
| Meldung | `The submission is too large.` |
| Ursache | Der Body, ein Feldname, ein Wert oder die Anzahl der Felder liegt über dem Limit. Die Meldung sagt, welches. |
| Lösung | Siehe [Limits](https://ikiform.com/de/docs/limits.md#submissions). Verteile langen Text auf mehrere Felder oder speichere Dateien woanders und sende einen Link. |

### 415 unsupported_media_type

|   |   |
| --- | --- |
| Meldung | `Send the form as urlencoded, multipart or JSON.` |
| Ursache | Der `Content-Type` ist nicht urlencoded, Multipart oder JSON, oder er fehlt. |
| Lösung | Setze `Content-Type: application/json`, wenn du JSON sendest. |

### 415 unsupported_charset

|   |   |
| --- | --- |
| Meldung | `Only UTF-8 is supported.` |
| Ursache | Der Body ist nicht UTF-8 oder deklariert einen anderen Zeichensatz. |
| Lösung | Kodiere als UTF-8. Füge alten HTML-Formularen `accept-charset="utf-8"` hinzu. |

### 422 validation_failed

|   |   |
| --- | --- |
| Meldung | `Some fields are invalid.` |
| Ursache | Felder haben die Validierung nicht bestanden. `error.fields` ordnet Feld-IDs Meldungen zu. |
| Lösung | Zeig die Meldungen neben den Feldern an. Siehe [Felder](https://ikiform.com/de/docs/fields.md#errors). |

### 422 files_not_supported

|   |   |
| --- | --- |
| Meldung | `File uploads are not supported yet.` |
| Ursache | Der Post enthält eine Datei. Datei-Uploads sind noch nicht gebaut. |
| Lösung | Entferne Datei-Inputs, oder lade Dateien woanders hoch und sende den Link. |

### 422 too_deep

|   |   |
| --- | --- |
| Meldung | `The JSON body is nested too deeply.` |
| Ursache | Der JSON-Body ist mehr als 3 Ebenen tief verschachtelt, das Objekt auf oberster Ebene mitgezählt. |
| Lösung | Mach die Daten flach, zum Beispiel `{ "address_city": "London" }`. |

### 422 idempotency_mismatch

|   |   |
| --- | --- |
| Meldung | `This idempotency key was already used with a different payload.` |
| Ursache | Dieser Idempotenzschlüssel wurde für dieses Formular in den letzten 24 Stunden schon mit anderen Feldern verwendet. |
| Lösung | Nutze einen neuen Schlüssel für neue Daten. Behalte denselben Schlüssel nur für exakte Wiederholungen. |

### 429 rate_limited

|   |   |
| --- | --- |
| Meldung | `Too many requests. Please slow down.` |
| Ursache | Rate-Limit überschritten. `Retry-After` gibt an, wie viele Sekunden du warten sollst. |
| Lösung | Warte und versuch es erneut. Wenn echte Besucher darauf stoßen, ändere das [Rate-Limit](https://ikiform.com/de/docs/rate-limits.md) des Formulars. |

### 429 quota_exceeded

|   |   |
| --- | --- |
| Meldung | `This form isn't accepting submissions right now.` |
| Ursache | Der Workspace hat diesen Monat das Doppelte seines monatlichen Einsendungslimits erhalten. |
| Lösung | Upgrade oder warte auf den nächsten Monat. Siehe [Monatliche Nutzung](https://ikiform.com/de/docs/limits.md#monthly-usage). |

### 500 server_error

|   |   |
| --- | --- |
| Meldung | `Something went wrong on our side.` |
| Ursache | Bei Ikiform ist etwas fehlgeschlagen. |
| Lösung | Versuch es mit Backoff und einem Idempotenzschlüssel erneut. Wenn es weiter passiert, gib die `request_id` an. |

## Keine Fehler

- Spam erhält dieselbe `201` oder Weiterleitung wie eine echte Einsendung. Du findest ihn im Dashboard unter dem Spamfilter.
- Ein nicht erlaubter `_redirect` wird ignoriert, und der Browser landet auf der gehosteten Danke-Seite.
- Ein `_replyto`, das keine einzelne gültige E-Mail-Adresse ist, wird ignoriert.

## Erneute Versuche

- Versuch `429` nach `Retry-After` erneut, und `500`, `409` oder Netzwerkfehler mit Backoff. Sende einen [Idempotenzschlüssel](https://ikiform.com/de/docs/frameworks.md#idempotency), damit ein erneuter Versuch nie ein Duplikat erzeugt.
- Versuch andere `4xx`-Fehler nicht unverändert erneut. Korrigiere zuerst den Request.
