Claude API の Python SDK を使い始めてすぐ、「公式ドキュメント通りにコードを書いたはずなのにエラーが出る」という経験をした方は多いのではないでしょうか。私自身も最初の数日間、ターミナルに赤いエラーが出るたびに何が悪いのか分からず、ドキュメントと実際の挙動のギャップに戸惑いました。
「どのエラーが出ているか」から逆引きできる構成にしていますので、エラーメッセージをそのまま見ながら読み進めていただけます。
前提:最初にやるべき環境確認
エラーの詳細に入る前に、環境が正しく整っているかを確認しましょう。以下のコマンドで SDK のバージョンと Python のバージョンを確認できます。
# インストール確認
pip show anthropic
# Pythonバージョン確認(3.8以上推奨)
python --versionSDK は頻繁に更新されるため、古いバージョンのままだと新しい機能が使えなかったり、ドキュメントと引数名が違う場合があります。初期セットアップ時は必ず最新版をインストールしましょう。
pip install -U anthropicエラー1: AuthenticationError — APIキーの設定ミス
エラーメッセージの例:
anthropic.AuthenticationError: Error code: 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}}
最初に遭遇しやすいエラーです。原因は主に3つあります。
原因A: APIキーをそのままコードに書いている
# ❌ やってはいけない
client = anthropic.Anthropic(api_key="sk-ant-api03-...")APIキーをコードに直書きすると、Gitリポジトリに誤ってプッシュしたときに漏洩します。GitHub のシークレットスキャンがアラートを出すこともあります。
✅ 正しい方法:環境変数を使う
import anthropic
import os
# 環境変数から読み込む
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))# ターミナルで設定(一時的)
export ANTHROPIC_API_KEY="sk-ant-api03-..."実は、anthropic.Anthropic() をインスタンス化するとき、api_key を省略すると SDK が自動で ANTHROPIC_API_KEY 環境変数を読んでくれます。そのため次のように書くのが最もシンプルです。
# 環境変数 ANTHROPIC_API_KEY が設定されていれば、これだけでOK
client = anthropic.Anthropic()原因B: .envファイルを読み込んでいない
.env ファイルを作成したのに読み込まれていないケースです。
# python-dotenvを使う
from dotenv import load_dotenv
load_dotenv() # この1行を忘れずに
import anthropic
client = anthropic.Anthropic()エラー2: RateLimitError (429) — レート制限に引っかかる
エラーメッセージの例:
anthropic.RateLimitError: Error code: 429 - {'type': 'error', 'error': {'type': 'rate_limit_error', 'message': 'Number of request tokens has exceeded your per-minute rate limit'}}
Claude API には「1分間に送れるトークン数」の制限があります。特に claude-opus-4-6 などの高性能モデルは、低いティアだと制限が厳しいです。
修正:エクスポネンシャルバックオフを実装する
ループでリクエストを送るコードを書いている場合、429が出たら待ってからリトライする実装が必要です。
import anthropic
import time
client = anthropic.Anthropic()
def call_with_retry(prompt: str, max_retries: int = 3) -> str:
"""429エラー時にリトライするラッパー関数"""
for attempt in range(max_retries):
try:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
except anthropic.RateLimitError as e:
if attempt == max_retries - 1:
raise # リトライ上限に達したら例外を再送出
wait_seconds = 2 ** attempt # 1秒 → 2秒 → 4秒
print(f"RateLimitError: {wait_seconds}秒待機してリトライ...")
time.sleep(wait_seconds)
result = call_with_retry("Pythonでフィボナッチ数列を実装してください")
print(result)大量のリクエストを送るバッチ処理の場合は、Batch API の利用も検討してみてください。非同期で処理され、レート制限の影響を受けにくくなります。
エラー3: BadRequestError (400) — モデル文字列・メッセージ形式の間違い
エラーメッセージの例:
anthropic.BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'model: value is not a valid enumeration member'}}
モデル名の文字列が間違っているときに出ます。Claude のモデル名は変更されることがあり、古い名前を使い続けているとこのエラーが出ます。
✅ 現在有効なモデル名(2026年5月時点):
# 利用可能なモデル文字列
MODEL_CLAUDE_OPUS = "claude-opus-4-6" # 最高性能
MODEL_CLAUDE_SONNET = "claude-sonnet-4-6" # バランス型(推奨)
MODEL_CLAUDE_HAIKU = "claude-haiku-4-5-20251001" # 高速・低コストモデル名はハードコードせず、定数として定義しておくと、将来のアップデート時に1箇所を変えるだけで済みます。
別の400エラー:messagesの形式ミス
# ❌ 間違い:contentが文字列ではなくリストになっていない
messages = [
{"role": "user", "content": "Hello"} # これはOK
]
# ❌ よくあるミス:userで終わっていない(Claude APIはuserで終わる必要がある)
messages = [
{"role": "user", "content": "こんにちは"},
{"role": "assistant", "content": "こんにちは!"} # assistantで終わるとエラー
]messages の最後は必ず "role": "user" で終わる必要があります。
エラー4: TypeError/IndexError — レスポンスの取り出し方を間違える
エラーメッセージが出ているわけではないですが、「なぜかレスポンスが取れない」というケースです。
❌ よくある間違い:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}]
)
# ❌ response は文字列ではなく Message オブジェクト
print(response) # 'Message' オブジェクトが表示される
# ❌ response.text は存在しない
print(response.text) # AttributeError✅ 正しい取り出し方:
# response.content はリスト(複数のブロックを含む可能性がある)
# テキスト応答の場合、最初の要素の .text を取得する
print(response.content[0].text)
# stop_reason で応答の終了理由を確認できる
print(response.stop_reason) # "end_turn", "max_tokens", "stop_sequence" など
# 使用トークン数を確認
print(f"入力: {response.usage.input_tokens} トークン")
print(f"出力: {response.usage.output_tokens} トークン")ツール呼び出し(Tool Use)を含む応答の場合、response.content に複数のブロックが含まれることがあります。その場合は型を確認してから処理してください。
for block in response.content:
if block.type == "text":
print("テキスト:", block.text)
elif block.type == "tool_use":
print("ツール呼び出し:", block.name, block.input)エラー5: ストリーミングで同期・非同期クライアントを混在させる
ストリーミングを試した際に「応答が来ない」「型エラーが出る」という相談をよく受けます。原因の多くは、同期クライアントと非同期クライアントの混在です。
❌ よくある間違い:通常のコードで非同期ストリーミングを使おうとする
import anthropic
import asyncio
client = anthropic.Anthropic() # 同期クライアント
# ❌ 同期クライアントに async stream を使おうとしている
async with client.messages.stream(...) as stream: # AttributeError
pass✅ 同期ストリーミングの正しい書き方:
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Pythonの基礎を教えてください"}]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)✅ 非同期ストリーミングの正しい書き方:
FastAPIやasyncioを使う場合は、anthropic.AsyncAnthropic を使います。
import anthropic
import asyncio
client = anthropic.AsyncAnthropic() # 非同期クライアント
async def main():
async with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Pythonの基礎を教えてください"}]
) as stream:
async for text in stream.text_stream:
print(text, end="", flush=True)
asyncio.run(main())同期コードには anthropic.Anthropic()、非同期コードには anthropic.AsyncAnthropic() を使うというルールを覚えておくと迷いません。
エラー6: OverloadedError (529) — サーバー混雑
エラーメッセージの例:
anthropic.InternalServerError: Error code: 529 - {'type': 'error', 'error': {'type': 'overloaded_error', 'message': 'Overloaded'}}
Anthropic のサーバーが混雑しているときに出るエラーです。ユーザー側のコードに問題はありませんが、リトライ処理を実装していないと処理が止まります。
529 エラーは 429(レート制限)と同様にバックオフしてリトライするのが基本です。先ほどの call_with_retry 関数を以下のように拡張できます。
import anthropic
import time
client = anthropic.Anthropic()
def call_with_retry(prompt: str, max_retries: int = 5) -> str:
"""429・529エラー時に対応するリトライ関数"""
retryable_errors = (anthropic.RateLimitError, anthropic.InternalServerError)
for attempt in range(max_retries):
try:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
except retryable_errors as e:
if attempt == max_retries - 1:
raise
wait = min(2 ** attempt, 60) # 最大60秒待機
print(f"{type(e).__name__}: {wait}秒後にリトライ ({attempt + 1}/{max_retries})")
time.sleep(wait)本番環境では Retry-After ヘッダー の値を使うとより正確な待機時間を設定できます。
エラー7: コンテキストウィンドウ超過 (400)
エラーメッセージの例:
anthropic.BadRequestError: Error code: 400 - {'message': 'prompt is too long: 220000 tokens > 200000 maximum'}
長い会話履歴や大きなファイルを送ったときに発生します。
# ❌ 無制限に会話履歴を保持し続けると最終的にエラー
conversation_history = []
while True:
user_input = input("You: ")
conversation_history.append({"role": "user", "content": user_input})
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=conversation_history # 蓄積し続けると上限に達する
)
# ...✅ 会話履歴を一定件数に制限する:
MAX_HISTORY_PAIRS = 20 # 最新20往復分のみ保持
def trim_history(history: list, max_pairs: int = MAX_HISTORY_PAIRS) -> list:
"""会話履歴を最新N往復分に切り詰める(システムプロンプトは保持)"""
if len(history) <= max_pairs * 2:
return history
return history[-(max_pairs * 2):]
conversation_history = []
while True:
user_input = input("You: ")
conversation_history.append({"role": "user", "content": user_input})
conversation_history = trim_history(conversation_history)
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=conversation_history
)
reply = response.content[0].text
conversation_history.append({"role": "assistant", "content": reply})
print(f"Claude: {reply}")長いコンテキストが必要な場合は、Prompt Caching を活用するとコストを大幅に削減できます。
まずはこの診断フローを手元に置いてください
エラーが出たとき、以下の順番で確認すると解決が早くなります。
- 401 → APIキーの設定確認(環境変数・.env読み込み)
- 429 → リトライ処理の追加・Batch APIの検討
- 400(モデル名) → 最新のモデル文字列に更新
- 400(メッセージ形式) → messagesがuserで終わっているか確認
- TypeError →
response.content[0].textの形式で取り出せているか確認 - 529 → バックオフ付きリトライ
- コンテキスト超過 → 会話履歴のトリミング実装
慣れてくると「このエラーはこう直す」がパターンとして身についてきます。最初は面食らいますが、今回紹介した7パターンで開発初期のほとんどのエラーはカバーできるはずです。
次のステップとして、本番環境に近い実装を作るには、Anthropic が提供している Python SDK のソースコード のサンプルコードも非常に参考になります。実際の例外クラスの継承関係も確認できるので、エラーハンドリングの精度が上がります。