アットウィキ(@WIKI)ご利用ガイド
エラーと制限
最終更新:
Bot(ページ名リンク)
-
view
エラーの形
このAPIがエラーを返すときは、必ず次の形のJSONを返す。
{"error":{"code":"not_found","message":"page not found"}}
エラーの種類を判定するときは `code` の値で分岐すること。`message` は人が読むための説明文で、事前の断りなく文言が変わることがあるので、判定には使わないこと。
エラーコード一覧
status(HTTPステータス)・code・意味・対処をまとめると次のとおり。対処が「リクエストを直す」の場合は、送った内容(パス・ヘッダー・ボディ)を見直して送り直すという意味。
| status | code | 意味 | 対処 |
| 400 | invalid_request | アクセストークンをURLのクエリ文字列やリクエストボディに入れて送った(Authorizationヘッダー以外にトークンがある) | リクエストを直す |
| 401 | unauthorized | アクセストークンの期限切れ(有効期限1時間)、Authorizationヘッダーが無い、クライアントが無効化された、権限(grant)が取り消し・失効しているなど、認可が通らない | まずリフレッシュトークンでアクセストークンを取り直す(最も多いのは期限切れ)。それでも401なら以下。ヘッダー欠落ならリクエストを直す。クライアントの無効化やgrant失効が原因の場合は、管理画面でアプリを有効化する、または再度同意画面を通す必要がある(この2つはトークンを取り直すだけでは解決しない) |
| 403 | insufficient_scope | 呼んだエンドポイントに必要なscopeをアクセストークンが持っていない | 必要なscopeを選び直してアプリを作り直す(登録後にscopeを変更する手段は無い)。登録できるアプリは3個までなので、上限に達しているときは不要なアプリを削除してから作る。作り直したら認可URLの `scope` にも書き加えて、トークンを取得し直す |
| 403 | role_insufficient | wikiでの自分のロール(管理者・副管理者など)がその操作に足りない | 対象wikiの管理者権限が必要(トークンを取り直しても解決しない) |
| 403 | page_forbidden | 対象ページ自体の閲覧・編集権限で弾かれた(scopeやロールとは別に、ページ単位の権限設定で拒否) | そのページの閲覧・編集権限が必要 |
| 403 | delete_scope_unapproved | `wiki:delete` scopeの運営承認が下りていない、または取り消された | 運営の承認が必要 |
| 404 | not_found | 指定したページ、またはURL自体が存在しない | リクエストを直す |
| 405 | method_not_allowed | そのURLに対応していないHTTPメソッドを使った | リクエストを直す |
| 409 | conflict | 同名ページが既にある、If-Matchが最新のetagと一致しない、同じIdempotency-Keyのリクエストが処理中など | ページ名の重複やIf-Match不一致はリクエストを直す。Idempotency-Keyが処理中の場合は少し待って再送する |
| 413 | payload_too_large | リクエストボディが1MiBを超えている | リクエストを直す |
| 415 | unsupported_media_type | Content-Typeがapplication/json以外 | リクエストを直す |
| 422 | invalid_parameter | pageid・cursorの値が不正、必須フィールド(検索の `q` など)の欠落・型違い、pagenameの変更、空本文、トップページ/メニューページの削除、検索へのcursor指定など、送った値そのものが不正 | リクエストを直す |
| 428 | precondition_required | DELETEでIf-Matchヘッダーを付けていない | リクエストを直す |
| 429 | rate_limit_exceeded | scopeごとの1時間あたりの上限を超えた | `Retry-After` レスポンスヘッダーの秒数だけ待ってから再送する(次のリセットまでの秒数が入る) |
| 500 | internal_error | サーバー側の想定外のエラー。原因はリクエスト内容に依らないことが多い | 自動で再試行しない。書き込み(POST・PUT・DELETE)で返ってきたときは、その書き込みが通っているかを`GET`で確かめる(`Idempotency-Key`を付けていれば同じキーで安全に再送できる)。続くようなら問い合わせる |
| 503 | service_unavailable | 認可基盤やレート制限の判定基盤に一時的な障害があり、安全に処理できない | `Retry-After` レスポンスヘッダー(`5`)の秒数だけ待ってから再送する |
注意:
- 401 `unauthorized` の応答では、`WWW-Authenticate` レスポンスヘッダーに `error="invalid_token"` のような値が入っていることがある。本文の `code` は常に `unauthorized` なので、エラー判定には本文の`code`を使うこと
リクエストの上限(レート制限)
scopeごとに1時間あたりの上限がある。
| scope | 1時間あたり |
| wiki:read | 1000 |
| wiki:search | 500 |
| user:read | 200 |
| wiki:write | 100 |
| wiki:delete | 50 |
応答には通常 `X-RateLimit-Limit`(上限)・`X-RateLimit-Remaining`(残り)・`X-RateLimit-Reset`(次にリセットされる時刻)が付くので、これを見ておくと上限にどれだけ近いか分かる(後述のfail-open時はこの3つの代わりに別のヘッダーになる)。
上限を超えると429 `rate_limit_exceeded` になる。このときの応答には `Retry-After` レスポンスヘッダーが付き、次にリセットされるまでの秒数が入っている。決め打ちの間隔で再送せず、この秒数だけ待つこと。
なお、制限を数えている基盤に一時的な不調があって上限を評価できないことがある。その場合、読み取り系(`wiki:read`・`wiki:search`・`user:read`)のリクエストは最大30秒までそのまま通し、応答に `X-RateLimit-Bypass: 1` が付く。30秒を超えて不調が続くと読み取り系も503 `service_unavailable` になる。書き込み(`wiki:write`)と削除(`wiki:delete`)は最初から安全側に倒して503 `service_unavailable` になる。
アプリのエラーと手前の層のエラーを見分ける
このAPI(アプリ)が返すエラーは必ずJSON。ただし、急に大量のリクエストを送った場合や、1MiBを超える大きなボディを送った場合は、アプリより手前の層がHTMLでエラーを返すことがある。
見分け方は `Content-Type` レスポンスヘッダー。`application/json` ならアプリのエラーなので、上のエラーコード一覧に従って対処する。それ以外(HTMLなど)なら手前の層のエラーなので、送信のペース(間隔)やボディのサイズを見直すこと。
ペースの目安は、概ね毎秒1リクエストを超えないこと。短時間のまとめ送りは多少許容されるが、それを超え続けると手前の層で弾かれる。並列で叩かず、1件ずつ順に送るのが安全。
手前の層も、リクエストが多すぎるときに429を返すことがある。これはアプリのレート制限(上の節の429 `rate_limit_exceeded`)とは別の仕組みで、応答はJSONではなくHTMLになる。429が返ってきたら、まず `Content-Type` を見て、アプリ側の制限なのか手前の層の制限なのかを切り分けること。
安全な取り扱い
- `client_secret` とトークンを公開リポジトリやブラウザで動くJavaScriptに置かない
- 削除は元に戻せないので、`GET` で対象を確かめてから `DELETE`
- scopeは必要なものだけ要求する。ただしアプリ登録後にscopeは変更できないので、使う予定のあるものは登録時に選んでおく
- トークンが漏れたら、管理画面でアプリを無効化する