# エラー

> Ikiform が返すすべてのエラーコードと、その HTTP ステータス、原因、対処。

フォームの送信と REST API は、同じエラーの形式を共有します。JSON のリクエストには対応する HTTP ステータスでこの形式が返り、ブラウザーからのフォーム送信には、同じメッセージとステータスでホストされたエラーページが表示されます。

## エラーの形式

`エラー`:

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

- `error.code` は安定しているので、分岐にはこれを使ってください。`error.message` は人が読むための平易な英語で、変わることがあります。
- `error.fields` はバリデーションエラーのときに含まれ、フィールド ID をキーに、それぞれメッセージの一覧を持ちます。ボディ全体に関するエラーはキー `_form` を使います。
- `error.challenge_url` は `challenge_required` のときに含まれます。
- `request_id` は、すべてのレスポンスに付く `X-Request-Id` ヘッダーと一致します。
- レート制限のレスポンスには、秒数を示す `Retry-After` が付きます。どちらのヘッダーもブラウザーのコードから読み取れます。

## コード

| ステータス | コード | 発生する場所 |
| --- | --- | --- |
| 400 | [`invalid_body`](#invalid-body) | 送信 |
| 400 | [`invalid_request`](#invalid-request) | API |
| 401 | [`unauthorized`](#unauthorized) | API |
| 402 | [`plan_required`](#plan-required) | 送信 |
| 403 | [`forbidden`](#forbidden) | 両方 |
| 403 | [`origin_not_allowed`](#origin-not-allowed) | 送信 |
| 403 | [`form_paused`](#form-paused) | 送信 |
| 403 | [`captcha_failed`](#captcha-failed) | 送信 |
| 403 | [`challenge_required`](#challenge-required) | 送信 |
| 404 | [`not_found`](#not-found) | 両方 |
| 405 | [`method_not_allowed`](#method-not-allowed) | API |
| 409 | [`idempotency_in_progress`](#idempotency-in-progress) | 送信 |
| 413 | [`payload_too_large`](#payload-too-large) | 送信 |
| 415 | [`unsupported_media_type`](#unsupported-media-type) | 送信 |
| 415 | [`unsupported_charset`](#unsupported-charset) | 送信 |
| 422 | [`validation_failed`](#validation-failed) | 送信 |
| 422 | [`files_not_supported`](#files-not-supported) | 送信 |
| 422 | [`too_deep`](#too-deep) | 送信 |
| 422 | [`idempotency_mismatch`](#idempotency-mismatch) | 送信 |
| 429 | [`rate_limited`](#rate-limited) | 両方 |
| 429 | [`quota_exceeded`](#quota-exceeded) | 送信 |
| 500 | [`server_error`](#server-error) | 両方 |

### 400 invalid_body

|   |   |
| --- | --- |
| メッセージ | `The request body could not be read.` |
| 原因 | JSON や multipart の形式が不正、オブジェクトではなく JSON の配列や文字列を送った、または冪等キーが 255 文字を超えている。 |
| 対処 | JSON のオブジェクトを 1 つ送るか、ブラウザーや `FormData` にボディを組み立てさせてください。 |

### 400 invalid_request

|   |   |
| --- | --- |
| メッセージ | `The request is invalid.` |
| 原因 | `limit`、`status`、`form_id`、`cursor` のいずれかが無効です。メッセージにそのパラメーター名が入ります。 |
| 対処 | `limit` は 1〜100、`status` は `received` か `spam`、実在する `frm_` の ID を使い、カーソルは返されたとおりに使ってください。 |

### 401 unauthorized

|   |   |
| --- | --- |
| メッセージ | `A valid API key is required.` |
| 原因 | `Authorization` ヘッダーがない、Bearer トークンではない、またはキーが存在しない、無効化された、期限切れ。 |
| 対処 | 有効なシークレットキーで `Authorization: Bearer ik_sk_...` を送ってください。 |

### 402 plan_required

|   |   |
| --- | --- |
| メッセージ | `This form isn't accepting submissions right now.` |
| 原因 | ワークスペースに有効なプランがありません。これはお支払いの仕組みが有効になって初めて起こりえます。 |
| 対処 | ダッシュボードの **Settings** でプランを選んでください。 |

### 403 forbidden

|   |   |
| --- | --- |
| メッセージ | `You do not have access to this resource.` |
| 原因 | API キーの形式が不正、別のワークスペースのもの、REST API で公開可能キーを使っている、または必要なスコープがない。 |
| 対処 | このワークスペースの、メッセージに示されたスコープを持つシークレットキーを使ってください。 |

### 403 origin_not_allowed

|   |   |
| --- | --- |
| メッセージ | `This form does not accept submissions from this site.` |
| 原因 | フォームの許可ドメイン外のサイトから送信され、フォームが不一致を拒否する設定になっている。または、キーに登録されていないドメインから公開可能キーが使われた。 |
| 対処 | サイトを **Allowed domains**（許可ドメイン）かキーのドメインに追加してください。サーバーからの送信には、シークレットキーを使ってください。 |

### 403 form_paused

|   |   |
| --- | --- |
| メッセージ | `This form is not accepting submissions right now.` |
| 原因 | ダッシュボードでフォームが一時停止されている。 |
| 対処 | フォームを再開してください。 |

### 403 captcha_failed

|   |   |
| --- | --- |
| メッセージ | `The captcha check failed. Please try again.` |
| 原因 | Turnstile のトークンがない、期限切れ、使用済み、または検証に失敗した。 |
| 対処 | 送信ごとに新しいトークンを取得してください。独自のキーを使う場合は、サイトキーがシークレットと対応しているか確認してください。 |

### 403 challenge_required

|   |   |
| --- | --- |
| メッセージ | `Complete the human check, then send the form again.` |
| 原因 | フォームが Ikiform の人間確認を使っていて、トークンのない JSON の送信が届いた。 |
| 対処 | SDK の `challenge(formId)` を呼び出してトークンを渡すか、`error.challenge_url` を使ってください。サーバーからの送信なら、代わりにシークレットキーを送れます。 |

### 404 not_found

|   |   |
| --- | --- |
| メッセージ | `Not found.` |
| 原因 | フォームが存在しない、削除または無効化された、または ID やルートが間違っている。`/f/<formId>` への `GET` でも返されます。 |
| 対処 | フォームの概要からエンドポイントをコピーし、タブで開くのではなく POST してください。 |

### 405 method_not_allowed

|   |   |
| --- | --- |
| メッセージ | `This method is not allowed here.` |
| 原因 | サーバー間専用の REST API に対する、ブラウザーのプリフライト。 |
| 対処 | `/api/v1` はバックエンドから呼び出してください。 |

### 409 idempotency_in_progress

|   |   |
| --- | --- |
| メッセージ | `A request with this idempotency key is still being processed.` |
| 原因 | この冪等キーのリクエストがまだ処理中です。 |
| 対処 | 少し待ってから同じキーでリトライしてください。最初の応答が返ります。 |

### 413 payload_too_large

|   |   |
| --- | --- |
| メッセージ | `The submission is too large.` |
| 原因 | ボディ、フィールド名、値、フィールドの数のいずれかが上限を超えている。どれかはメッセージに示されます。 |
| 対処 | [制限](https://ikiform.com/ja/docs/limits.md#submissions)を参照してください。長いテキストは複数のフィールドに分けるか、ファイルは別の場所に保存してリンクを送ってください。 |

### 415 unsupported_media_type

|   |   |
| --- | --- |
| メッセージ | `Send the form as urlencoded, multipart or JSON.` |
| 原因 | `Content-Type` が urlencoded、multipart、JSON のいずれでもない、または指定されていない。 |
| 対処 | JSON を送るときは `Content-Type: application/json` を設定してください。 |

### 415 unsupported_charset

|   |   |
| --- | --- |
| メッセージ | `Only UTF-8 is supported.` |
| 原因 | ボディが UTF-8 ではない、または別の文字コードを宣言している。 |
| 対処 | UTF-8 でエンコードしてください。古い HTML フォームには `accept-charset="utf-8"` を追加してください。 |

### 422 validation_failed

|   |   |
| --- | --- |
| メッセージ | `Some fields are invalid.` |
| 原因 | フィールドがバリデーションに失敗した。`error.fields` はフィールド ID をメッセージに対応づけます。 |
| 対処 | メッセージをフィールドの横に表示してください。[フィールド](https://ikiform.com/ja/docs/fields.md#errors)を参照してください。 |

### 422 files_not_supported

|   |   |
| --- | --- |
| メッセージ | `File uploads are not supported yet.` |
| 原因 | 送信にファイルが含まれている。ファイルのアップロードはまだ実装されていません。 |
| 対処 | ファイルの入力欄を削除するか、ファイルは別の場所にアップロードしてリンクを送信してください。 |

### 422 too_deep

|   |   |
| --- | --- |
| メッセージ | `The JSON body is nested too deeply.` |
| 原因 | JSON のボディが、トップレベルのオブジェクトを含めて 3 階層を超えてネストしている。 |
| 対処 | `{ "address_city": "London" }` のように、データを平らにしてください。 |

### 422 idempotency_mismatch

|   |   |
| --- | --- |
| メッセージ | `This idempotency key was already used with a different payload.` |
| 原因 | この冪等キーは、直近 24 時間以内にこのフォームで、異なるフィールドとともにすでに使われている。 |
| 対処 | 新しいデータには新しいキーを使ってください。同じキーは完全に同じリトライにだけ使ってください。 |

### 429 rate_limited

|   |   |
| --- | --- |
| メッセージ | `Too many requests. Please slow down.` |
| 原因 | レート制限を超えた。`Retry-After` に待つべき秒数が示されます。 |
| 対処 | 待ってからリトライしてください。本物の訪問者が制限に達する場合は、フォームの[レート制限](https://ikiform.com/ja/docs/rate-limits.md)を変更してください。 |

### 429 quota_exceeded

|   |   |
| --- | --- |
| メッセージ | `This form isn't accepting submissions right now.` |
| 原因 | ワークスペースが今月、月間の送信数の上限の 2 倍を受信した。 |
| 対処 | アップグレードするか、翌月まで待ってください。[月間の使用量](https://ikiform.com/ja/docs/limits.md#monthly-usage)を参照してください。 |

### 500 server_error

|   |   |
| --- | --- |
| メッセージ | `Something went wrong on our side.` |
| 原因 | Ikiform 側で問題が発生した。 |
| 対処 | バックオフと冪等キーを使ってリトライしてください。問題が続く場合は、`request_id` を伝えてください。 |

## エラーにならないもの

- スパムにも、本物の送信と同じ `201` またはリダイレクトが返ります。ダッシュボードのスパムフィルターの下で確認してください。
- 許可されていない `_redirect` は無視され、ブラウザーはホストされたサンクスページに移動します。
- 有効なメールアドレス 1 つではない `_replyto` は無視されます。

## リトライ

- `429` は `Retry-After` の後に、`500`、`409`、ネットワークエラーはバックオフを付けてリトライしてください。[冪等キー](https://ikiform.com/ja/docs/frameworks.md#idempotency)を送れば、リトライで重複が作られることはありません。
- その他の `4xx` エラーは、そのままリトライしないでください。先にリクエストを直してください。
