エンジニアの思い立ったが吉日

このブログでは、「あ、これ面白い!」「明日から仕事で使えそう!」と感じたIT関連のニュースやサービスを、難しい言葉を使わずに分かりやすく紹介しています。ITに詳しくない方にも楽しんでもらえるような情報を発信していくので、ぜひ「継続的な情報収集」の場としてご活用ください。

Claude APIのエラーコード完全ガイド|原因・対処法・実装パターンを徹底解説

「また429エラーだ……」「500番台のエラーが出たけど、これってAPI側の問題?こっちの問題?」

Claude APIを使ってアプリやシステムを開発していると、こういった場面に必ず直面します。エラーは避けられないもの。大切なのは、エラーの意味を素早く理解し、正確な対処ができることです。

この記事では、Claude APIで発生しうるすべてのHTTPエラーコードを体系的に整理し、原因の深掘りから実際のコード例まで網羅的に解説します。さらに、単なるエラー対処にとどまらず、エラーを「出さない」設計思想やプロダクションレベルのエラーハンドリング実装まで踏み込みます。Claude API開発のリファレンスとしてブックマーク必須の内容です。

Claude APIのエラーの全体構造を理解する

エラーはなぜ起きるのか?3つの発生源

Claude APIのエラーは、大きく分けて3つの発生源があります。これを最初に理解しておくと、エラーを見た瞬間に「どこを直せばいいか」が判断できるようになります。

発生源 代表的なHTTPコード 主なケース
クライアント側の問題(自分のコード) 400, 401, 403, 404, 413 リクエスト形式の誤り、認証キーの問題、パラメータのミス
トラフィック・使用量の問題 429 レート制限超過、急激なリクエスト増加
サーバー側の問題(Anthropic側) 500, 529 内部障害、高負荷状態

この分類を知っておくと、「自分が直すべきか」「待てば解消するか」 がすぐに判断できます。

エラーレスポンスの形式

APIは常にJSONでエラーを返し、トップレベルのerrorオブジェクトにtypemessageが含まれます。またrequest_idフィールドも含まれており、トラブルシューティングに役立ちます。

{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "message": "The requested resource could not be found."
  },
  "request_id": "req_011CSHoEeqs5C35K2UUqR7Fy"
}

すべてのAPIレスポンスには固有のrequest-idヘッダーが含まれます。サポートに特定のリクエストについて問い合わせる際は、このIDを添えると迅速に解決できます。


4xx系エラーコード:クライアント側で解決すべきエラー

4xx系は自分のコードやリクエストに問題があることを示します。しっかり原因を理解して修正しましょう。

400 invalid_request_error:リクエストの形式・内容が不正

400エラーは、リクエストのフォーマットや内容に問題がある場合に発生します。下記に挙げていない他の4xxステータスコードにもこのエラータイプが使われることがあります。

主な原因

  • messagesパラメータの形式が配列でない
  • role"user""assistant"以外の値になっている
  • max_tokensが未指定、または0以下
  • コンテキストウィンドウ(最大20万トークン)を超えている
  • JSON自体が不正(括弧の閉じ忘れなど)

よくあるミスと修正例

# ❌ よくある間違い:messagesが文字列になっている
messages = "こんにちは"

# ✅ 正しい形式:配列の中にオブジェクトで記述
messages = [
    {"role": "user", "content": "こんにちは"}
]
# ❌ よくある間違い:max_tokensの指定漏れ
response = client.messages.create(
    model="claude-sonnet-4-6",
    messages=[{"role": "user", "content": "要約して"}]
)

# ✅ 正しい:max_tokensは必須
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "要約して"}]
)

実践的な対処法

  1. リクエストボディをjson.dumps()で文字列化し、JSONバリデーターで確認する
  2. コンテキストウィンドウ超過が疑われる場合は、入力テキストのトークン数を事前にカウントAPI(/v1/messages/count_tokens)で計測する
  3. Claude Codeを使っている場合、.claudeignoreファイルでnode_modulesやビルド成果物などを除外するとコンテキスト肥大化を防げる

401 authentication_error:APIキー認証の失敗

APIキーに問題があるエラーです。本番環境でよく見落とされがちなのが、環境変数のコピペ時に混入した不可視文字(スペース・改行) です。

主な原因

  • APIキー自体が無効・失効している
  • 環境変数ANTHROPIC_API_KEYが設定されていない
  • APIキーの文字列にスペースや改行が混入している
  • APIキーのプレフィックス(sk-ant-api03-)が欠落している

確認・修正手順

# 設定されているAPIキーを確認(値が空でないか・スペースが混入していないか)
echo "[$ANTHROPIC_API_KEY]"

# 正しく設定し直す
export ANTHROPIC_API_KEY="sk-ant-api03-xxxxxxxxxxxx"
# Pythonコードでの確認
import os

api_key = os.environ.get("ANTHROPIC_API_KEY", "")
print(f"APIキー長: {len(api_key)}")
print(f"プレフィックス確認: {api_key[:15]}")

注意点:本番環境でAPIキーをハードコードするのは厳禁です。.envファイルや、AWSのSecrets Manager・GCPのSecret Managerなどの秘密管理サービスを使いましょう。


403 permission_error:アクセス権限の不足

主な原因

  • APIキーに特定モデルや機能へのアクセス権がない
  • 組織レベルでアクセス制限が設定されている
  • Batch APIなど一部機能が利用可能なティアに達していない

対処法Anthropic ConsoleでAPIキーの権限設定を確認し、組織管理者に問い合わせるか、必要に応じてAnthropicのサポートに連絡します。


404 not_found_error:リソースが見つからない

最もよくある原因はモデル名のタイポです。Claude 4系のモデルが登場した現在、古いモデル名を使ってしまうケースが増えています。

正しいモデル名の確認方法

# ❌ よくある間違い例(古い形式や不完全な名前)
model = "claude-3-sonnet"        # バージョン情報が不足
model = "claude-sonnet"          # 不完全

# ✅ 2025年時点の正しいモデル名例
model = "claude-opus-4-6"
model = "claude-sonnet-4-6"
model = "claude-haiku-4-5-20251001"

最新のモデル名は必ず公式ドキュメントのModelsページで確認することをお勧めします。ハードコードせず、設定ファイルや環境変数で管理すると更新が容易です。


413 request_too_large:リクエストサイズの超過

APIにはエンドポイントごとにリクエストサイズの上限が設けられています。

エンドポイント 最大リクエストサイズ
Messages API 32 MB
Token Counting API 32 MB
Batch API 256 MB
Files API 500 MB

制限を超えた場合、リクエストがAPIサーバーに届く前にCloudflareから413エラーが返されます。

対処法

  • 大きなPDFや画像を送信する際は、ファイルを分割するか解像度を落とす
  • 画像は最大8000×8000pxを目安にリサイズする
  • Files APIを活用してファイルをアップロードし、参照IDで指定することでリクエストサイズを削減できる

429 rate_limit_error:最も遭遇しやすいレート制限エラー

開発・本番運用を問わず、最も頻繁に遭遇するエラーです。ただし、適切な実装で完全にコントロールできます。

レート制限の仕組みを正確に理解する

レート制限はRPM(リクエスト/分)、ITPM(入力トークン/分)、OTPM(出力トークン/分)の3軸で管理されています。いずれかの制限を超えると429エラーが返り、retry-afterヘッダーで待機時間が通知されます。

APIはトークンバケットアルゴリズムでレート制限を実装しています。これにより、固定インターバルでリセットされるのではなく、上限まで継続的に容量が補充されます。

重要:RPMは「1分あたり」でも均等ではない

例えば60RPMのレート制限は、1秒あたり1リクエストとして適用される場合があります。短時間の集中したリクエストは制限を超えてしまう可能性があります。

これは見落としやすいポイントです。「60RPMだから1分間に60回送っても大丈夫」と思っても、1秒以内に複数リクエストを送ると制限に引っかかります。

プロンプトキャッシュでITPM制限を事実上引き上げる

多くのAPIプロバイダーは、キャッシュされたトークンと未キャッシュのトークンを合算してレート制限を計算しますが、ほとんどのClaudeモデルでは未キャッシュの入力トークンのみがITPMレート制限にカウントされます。

たとえばITPM制限が200万で、キャッシュヒット率が80%の場合、キャッシュされたトークンは制限にカウントされないため、実効的に毎分1000万トークン(200万の未キャッシュ + 800万のキャッシュ済み)を処理できます。

つまり、システムプロンプトや長い文脈ドキュメントをキャッシュするだけで、スループットを最大5倍に引き上げられるケースがあります。

指数バックオフによる堅牢なリトライ実装

import time
import random
import anthropic

def call_with_exponential_backoff(
    client: anthropic.Anthropic,
    max_retries: int = 5,
    base_delay: float = 1.0,
    **kwargs
):
    """
    指数バックオフ + ジッター付きのリトライ実装
    
    ジッター(ランダム要素)を加えることで、複数クライアントが
    同時にリトライして再びレート制限に引っかかる「雷鳴の群れ問題」を回避
    """
    for attempt in range(max_retries):
        try:
            return client.messages.create(**kwargs)
        
        except anthropic.RateLimitError as e:
            if attempt == max_retries - 1:
                raise  # 最大リトライ数到達時は例外を伝播
            
            # 指数バックオフ: 1→2→4→8→16秒
            wait_time = base_delay * (2 ** attempt)
            # ジッター: ±25%のランダム変動を加える
            jitter = wait_time * 0.25 * (random.random() * 2 - 1)
            actual_wait = wait_time + jitter
            
            print(f"レート制限 (試行 {attempt + 1}/{max_retries}): "
                  f"{actual_wait:.1f}秒後にリトライします...")
            time.sleep(actual_wait)

# 使用例
client = anthropic.Anthropic()
response = call_with_exponential_backoff(
    client,
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "こんにちは"}]
)

レスポンスヘッダーで使用量をリアルタイム監視する

APIレスポンスには、適用されているレート制限・現在の使用量・リセットタイミングを示すヘッダーが含まれます。

ヘッダー 内容
retry-after リトライまでの待機秒数
anthropic-ratelimit-requests-limit 許容される最大リクエスト数
anthropic-ratelimit-requests-remaining 残りリクエスト数
anthropic-ratelimit-requests-reset リクエスト制限のリセット時刻(RFC 3339形式)
anthropic-ratelimit-input-tokens-remaining 残り入力トークン数(千単位で丸め)
anthropic-ratelimit-output-tokens-remaining 残り出力トークン数(千単位で丸め)
# レスポンスヘッダーから使用量を取得して監視する実装例
import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "テスト"}]
)

# SDKではレスポンスオブジェクトからrequest_idを取得可能
print(f"Request ID: {response._request_id}")

# HTTPヘッダーはSDKの内部オブジェクトから取得
# (実装によってはrawヘッダーへのアクセス方法が異なります)

5xx系エラーコード:Anthropic側の問題

5xx系はAnthropicのサーバー側で発生した問題です。自分のコードを修正しても解決しないため、ステータス確認とリトライが基本的な対処法になります。

500 api_error:内部サーバーエラー

Anthropic側の予期しない問題です。

対処フロー

  1. Claude Status Pageを開いてインシデント情報を確認
  2. 1〜5分待機してからリトライ
  3. 繰り返し発生する場合は、エラーレスポンスに含まれるrequest_idを記録してサポートに連絡

529 overloaded_error:サーバー高負荷

529エラーは、APIが全ユーザーにわたって高いトラフィックを経験している際に発生します。

対処法

  • 2〜5分待機してからリトライ(単純な待機が最も効果的)
  • Claude Opusなど重いモデルを使用中であれば、Sonnetへの切り替えを検討
  • タスクをより小さなチャンクに分割して送信
  • ピーク時間帯(日本時間の深夜〜早朝が米国の昼間に重なりトラフィックが増える傾向)を避けたバッチ処理スケジューリング

プロダクション品質のエラーハンドリング実装

すべてのエラーを網羅する完全実装

import anthropic
import time

client = anthropic.Anthropic()

def robust_api_call(
    prompt: str,
    model: str = "claude-sonnet-4-6",
    max_tokens: int = 1024,
    max_retries: int = 3
) -> str:
    """
    プロダクション品質のClaude API呼び出し関数
    - 全エラータイプへの対処
    - 自動リトライ(リトライすべきエラーのみ)
    - ログ出力
    """
    
    # リトライすべきエラー(一時的な問題)
    RETRYABLE_ERRORS = (
        anthropic.RateLimitError,
        anthropic.InternalServerError,
    )
    
    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model=model,
                max_tokens=max_tokens,
                messages=[{"role": "user", "content": prompt}]
            )
            return response.content[0].text
            
        except anthropic.BadRequestError as e:
            # 400: コードのバグ。リトライ不要
            print(f"[ERROR] リクエスト形式が不正です: {e}")
            print("→ messagesの形式、max_tokens、モデル名を確認してください")
            raise  # 上位に伝播して修正を促す
            
        except anthropic.AuthenticationError as e:
            # 401: APIキーの問題。リトライ不要
            print(f"[ERROR] 認証エラー: {e}")
            print("→ ANTHROPIC_API_KEY環境変数を確認してください")
            raise
            
        except anthropic.PermissionDeniedError as e:
            # 403: 権限の問題。リトライ不要
            print(f"[ERROR] 権限エラー: {e}")
            print("→ Anthropic Consoleでキーの権限を確認してください")
            raise
            
        except anthropic.NotFoundError as e:
            # 404: モデル名などの間違い。リトライ不要
            print(f"[ERROR] リソース未発見: {e}")
            print("→ モデル名を公式ドキュメントで確認してください")
            raise
            
        except RETRYABLE_ERRORS as e:
            # 429, 500, 529: 一時的な問題。リトライする
            if attempt == max_retries - 1:
                print(f"[ERROR] {max_retries}回リトライしましたが解決しませんでした: {e}")
                raise
                
            wait_time = 2 ** attempt * 2  # 2, 4, 8秒
            error_type = type(e).__name__
            print(f"[WARN] {error_type} (試行{attempt + 1}/{max_retries}): "
                  f"{wait_time}秒後にリトライします...")
            time.sleep(wait_time)
            
        except anthropic.APIError as e:
            # その他の予期しないAPIエラー
            print(f"[ERROR] 予期しないAPIエラー: {e}")
            raise

# 使用例
try:
    result = robust_api_call("日本のAI市場の最新動向を3点で要約してください")
    print(result)
except Exception as e:
    print(f"処理を中断しました: {e}")

長時間リクエストの安全な処理

10分以上かかる長時間のリクエストには、ストリーミングMessages APIまたはMessage Batches APIの使用を強く推奨します。

ネットワークによってはアイドル接続を一定時間後に切断するものがあり、Anthropicからのレスポンスを受け取れずにリクエストが失敗またはタイムアウトする可能性があります。

# 長時間タスクにはストリーミングを使う
import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-opus-4-6",
    max_tokens=4096,
    messages=[{"role": "user", "content": "長い文書を詳細に分析してください..."}]
) as stream:
    for text_chunk in stream.text_stream:
        print(text_chunk, end="", flush=True)
    
    # 最終的なメッセージオブジェクトを取得
    final_message = stream.get_final_message()

エラーを「出さない」設計:予防的アプローチ

エラーが出てから対処するのではなく、そもそもエラーが起きにくい設計を目指すことが重要です。

エラー予防のためのチェックリスト

カテゴリ チェック項目 実装例
認証 APIキーを環境変数で管理 .env + python-dotenv
モデル名 設定ファイルで一元管理 config.pyにモデル名定数を定義
トークン管理 リクエスト前にトークン数を計測 /v1/messages/count_tokens APIを活用
レート制限 リクエスト間隔にスリープを入れる バッチ処理でのスロットリング
キャッシュ 繰り返し使うシステムプロンプトをキャッシュ cache_controlパラメータを設定
監視 レスポンスヘッダーで使用量を記録 ログにトークン使用量を出力
フォールバック Anthropic障害時の代替手段を用意 AWS BedrockやVertex AI経由でのClaude利用

ワークスペース分離でリスクを管理する

ワークスペースごとにカスタムの使用量・レート制限を設定することで、潜在的な過剰使用からワークスペースを守り、組織内のリソースを公平に分配できます。

例えば、開発環境と本番環境でワークスペースを分け、開発環境には低いレート制限を設定することで、開発中の暴走リクエストが本番に影響しないよう守れます。


他のAI APIとのエラーハンドリング比較

Claude APIのエラーハンドリングは、他の主要なAI APIと比較してどうでしょうか?

比較項目 Claude API OpenAI API Google Gemini API
エラー形式 JSON(typeとmessage) JSON(codeとmessage) JSON(statusとmessage)
レート制限通知 retry-afterヘッダー retry-afterヘッダー レスポンスボディに含む
request_id ✅ 全レスポンスに含む ✅ 含む 一部のみ
トークンバケット方式 ✅ 採用(細かい制御) 固定ウィンドウ方式 固定ウィンドウ方式
キャッシュトークンのレート制限除外 ✅ 対応(大半のモデル) ❌ 非対応 ❌ 非対応
公式SDKのリトライ機能 ✅(Python/TypeScript) ✅(Python/Node.js) ✅(Python/Node.js)
ステータスページ status.anthropic.com status.openai.com status.cloud.google.com

Claude APIの強みは、キャッシュトークンがレート制限にカウントされない点と、トークンバケット方式による細かいレート制御です。特に大量のコンテキストを繰り返し使うアプリケーションでは、他のAPIと比べてスループットで優位になれます。


まとめ:Claude APIエラー対処の3原則

ここまでの内容を3つの原則に集約します。

原則1:エラーの性質を見極めて対処を変える - 4xx系 → 自分のコードを修正する - 429 → 待機してリトライ or キャッシュ活用 - 5xx系 → ステータスページを確認しながら待機

原則2:リトライは必ず指数バックオフで 同じタイミングで大量のリクエストが集中するとサーバー負荷をさらに上げてしまいます。ランダムなジッター(ばらつき)を加えた指数バックオフが業界標準の実装です。

原則3:エラーを「出さない」設計を優先する プロンプトキャッシュの活用・トークン数の事前計測・段階的なトラフィック増加、これらを意識することで429エラーの大半は未然に防げます。

次のステップとして、まずは本記事のコードサンプルを自分のプロジェクトにそのまま組み込んでみてください。その後、Anthropic ConsoleのUsageページでレート制限の使用状況を定期的に確認する習慣をつけると、本番運用の安定性が大きく向上します。


参考リンク

engineer-kichizitsu.net

engineer-kichizitsu.net

engineer-kichizitsu.net

engineer-kichizitsu.net

engineer-kichizitsu.net

当サイトは、アフィリエイト広告を使用しています。