エラー処理とレートリミット
重要キーワード (4 語)
Rate Limit
(レートリミット)
— 単位時間あたりの呼び出し上限 (RPM/TPM)
Exponential Backoff
(指数バックオフ)
— 失敗ごとに待機時間を倍々で伸ばすリトライ戦略
Idempotency
(冪等性)
— 同じ操作を何度繰り返しても結果が変わらない性質
Retry-After
(リトライ後待機時間)
— 429 で返るヘッダ。次の試行までの待ち秒数
エラー処理
Anthropic SDK は HTTP ステータスに応じた例外クラスを返します。
| 例外 | ステータス | 意味 |
|---|---|---|
BadRequestError |
400 | リクエスト不正 |
AuthenticationError |
401 | API キー誤り |
PermissionDeniedError |
403 | 権限不足 |
NotFoundError |
404 | モデル ID 等が無効 |
RateLimitError |
429 | レート上限超え |
APIStatusError |
5xx | サーバー側エラー |
APIConnectionError |
- | 通信失敗 |
リトライ付きの呼び出し
from anthropic import (
Anthropic, RateLimitError, APIStatusError, BadRequestError
)
import time, random
def safe_call(prompt, retries=5):
for i in range(retries):
try:
return client.messages.create(
model="claude-sonnet-4-6",
max_tokens=512,
messages=[{"role": "user", "content": prompt}],
)
except RateLimitError:
wait = 2 ** i + random.random()
print(f"rate limited, retry in {wait:.1f}s")
time.sleep(wait)
except APIStatusError as e:
if 500 <= e.status_code < 600 and i < retries - 1:
time.sleep(2 ** i)
continue
raise
raise RuntimeError("max retries reached")
SDK 標準のリトライ機構
Anthropic(max_retries=3, timeout=60) のように、SDK 自体にもリトライ・タイムアウト設定があります。
シンプルな用途ならまずはこちらで十分。
レートリミット (Rate Limit)
Anthropic はティアごとに RPM (リクエスト/分), TPM (トークン/分) が決まっています。 - 開発初期: 低い上限。 - 使用量・支払いが増えると 自動昇格 または申請で引き上げ可能。
Retry-After ヘッダ
429 のレスポンスには retry-after ヘッダが含まれることがあるので、
これを尊重して待機するのが行儀の良い実装です。SDK は自動で読みます。
Idempotency (冪等性)
同じリクエストを再送しても安全か? Anthropic の messages API は副作用なし なので、リトライしても問題ありません。 ただしユーザー側でログ・課金処理を多重に走らせないよう注意。
よく出るエラーと診断
| エラーメッセージ | 原因 | 対処 |
|---|---|---|
Invalid API Key |
キーが間違い・失効 | Console で確認 |
model not found |
モデル ID 誤り | claude-sonnet-4-6 のような正しい ID |
max_tokens too large |
プランの上限超え | 引き下げる |
prompt is too long |
コンテキスト超過 | 入力短縮 / モデル変更 |
429 |
レート超過 | バックオフ |
overloaded_error |
サーバー過負荷 | バックオフして再試行 |
サーキットブレーカー
連続して失敗するときは 一時停止 (circuit breaker) を入れて、 下流サービスが過負荷で潰れるのを防ぎます。
class Breaker:
def __init__(self, threshold=5, cooldown=60):
self.fails = 0
self.opened_at = None
self.threshold = threshold
self.cooldown = cooldown
def call(self, fn, *a, **kw):
if self.opened_at and (time.time() - self.opened_at) < self.cooldown:
raise RuntimeError("circuit open")
try:
r = fn(*a, **kw)
self.fails = 0
return r
except Exception:
self.fails += 1
if self.fails >= self.threshold:
self.opened_at = time.time()
raise
観察
エラー応答もモデルに考えさせると面白い学びになります。
あなたは API クライアント設計をレビューする SRE です。Anthropic API の RateLimitError と APIStatusError(5xx) に対するリトライ戦略を、擬似コードで提示してください。考慮点も箇条書きで。