CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-03-21初級

Claude API 初めてのリクエストが失敗する?よくあるエラー FAQ

Claude API 初心者向けエラー解決ガイド。401認証エラー、429レート制限、400不正リクエスト、空レスポンス、ストリーミング失敗、tool_use、context window超過、tool_result submission、Spanner temporarily unavailable など9つのよくあるエラーの原因と解決法を網羅。

Claude API115Anthropic SDK4エラー6初心者7FAQ2

Claude API を初めて使用する際、さまざまなエラーが発生することがあります。認証エラー、レート制限、リクエスト形式エラーなど、最初の API 呼び出しでぶつかりやすい9つの問題と、その解決方法をご説明します。

Q1: 401 認証エラー(Unauthorized)または API キーが認識されない

原因

API キーが設定されていない、無効であるか、または形式が間違っています。

解決法

ステップ1:API キーを確認

  1. Anthropic コンソール にログイン
  2. 「API Keys」セクションで新しいキーを生成
  3. キーをコピー(sk-ant- で始まります)

ステップ2:API キーを設定

Python の場合:

import anthropic
 
# 方法1:環境変数(推奨)
# 実行前に:export ANTHROPIC_API_KEY="sk-ant-..."
client = anthropic.Anthropic()  # 自動的に ANTHROPIC_API_KEY を読み込む
 
# 方法2:直接指定(テスト時のみ)
client = anthropic.Anthropic(api_key="sk-ant-your-key-here")
 
# 方法3:確認
print(client.api_key)  # 最初の数文字のみ表示される

Node.js/JavaScript の場合:

import Anthropic from "@anthropic-ai/sdk";
 
// 方法1:環境変数(推奨)
// 実行前に:export ANTHROPIC_API_KEY="sk-ant-..."
const client = new Anthropic();  // 自動的に環境変数を読み込む
 
// 方法2:直接指定
const client = new Anthropic({
  apiKey: "sk-ant-your-key-here",
});

cURL の場合:

# ヘッダーに API キーを指定
curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: sk-ant-your-key-here" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{...}'

ステップ3:環境変数を確認

# API キーが設定されているか確認
echo $ANTHROPIC_API_KEY
 
# 最初の10文字が表示されるか確認
echo $ANTHROPIC_API_KEY | head -c 10

ステップ4:キーの有効性をテスト

# cURL でテスト
curl -s https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-opus-4-1","messages":[{"role":"user","content":"test"}],"max_tokens":100}' \
  | head -c 200
 
# 200 OK が返ればキーは有効

:::warning API キー漏洩時の対応:

  1. コンソールで問題のキーを削除
  2. 新しいキーを生成
  3. コード内で新しいキーに置き換え
  4. git commit 履歴を確認(キーが含まれていないか)

漏洩したキーで実行された API 呼び出しについては、Anthropic サポートに連絡してください。 :::


Q2: 429 エラー(Too Many Requests)- レート制限に達した

原因

API の使用制限(分単位、日単位のレート制限)に達しました。または大量のリクエストを短時間で送信しています。

解決法

ステップ1:レート制限の内容を確認

# レスポンスヘッダーを確認
curl -i https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{...}'
 
# レスポンスに以下が含まれます:
# x-ratelimit-limit-requests: 6000
# x-ratelimit-limit-tokens: 2000000
# x-ratelimit-remaining-requests: 5999
# x-ratelimit-reset-requests: 2026-03-21T18:05:00Z

ステップ2:リトライロジックを実装

Python の例:

import anthropic
import time
from typing import Optional
 
def call_claude_with_retry(
    client: anthropic.Anthropic,
    max_retries: int = 5,
    backoff_factor: float = 2.0
) -> Optional[str]:
    """リトライロジック付きの API 呼び出し"""
 
    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model="claude-opus-4-1",
                max_tokens=1024,
                messages=[
                    {"role": "user", "content": "Hello, Claude!"}
                ]
            )
            return response.content[0].text
 
        except anthropic.RateLimitError as e:
            if attempt == max_retries - 1:
                raise  # 最後の試行で失敗した場合は例外を投げる
 
            # 指数バックオフで待機
            wait_time = backoff_factor ** attempt
            print(f"Rate limited. Waiting {wait_time} seconds...")
            time.sleep(wait_time)
 
        except anthropic.APIError as e:
            print(f"API Error: {e}")
            raise
 
# 使用例
client = anthropic.Anthropic()
result = call_claude_with_retry(client)
print(result)

Node.js の例:

import Anthropic from "@anthropic-ai/sdk";
 
async function callClaudeWithRetry(
  client,
  maxRetries = 5,
  backoffFactor = 2.0
) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await client.messages.create({
        model: "claude-opus-4-1",
        max_tokens: 1024,
        messages: [{ role: "user", content: "Hello, Claude!" }],
      });
 
      return response.content[0].text;
    } catch (error) {
      if (error.status === 429) {
        if (attempt === maxRetries - 1) throw error;
 
        const waitTime = Math.pow(backoffFactor, attempt) * 1000;
        console.log(`Rate limited. Waiting ${waitTime}ms...`);
        await new Promise((resolve) => setTimeout(resolve, waitTime));
      } else {
        throw error;
      }
    }
  }
}
 
const client = new Anthropic();
const result = await callClaudeWithRetry(client);
console.log(result);

ステップ3:リクエストの並行処理を制限

# ❌ 悪い例(並行リクエストが多すぎる)
import asyncio
 
async def bad_example():
    tasks = [
        client.messages.create(
            model="claude-opus-4-1",
            max_tokens=100,
            messages=[{"role": "user", "content": f"Task {i}"}]
        )
        for i in range(100)  # 100 個を同時実行
    ]
    return await asyncio.gather(*tasks)
 
# ✅ 良い例(並行数を制限)
import asyncio
from asyncio import Semaphore
 
async def good_example():
    semaphore = Semaphore(5)  # 最大 5 個の並行リクエスト
 
    async def limited_request(i):
        async with semaphore:
            return await client.messages.create(
                model="claude-opus-4-1",
                max_tokens=100,
                messages=[{"role": "user", "content": f"Task {i}"}]
            )
 
    tasks = [limited_request(i) for i in range(100)]
    return await asyncio.gather(*tasks)

:::tip フリーティアと有料アカウントで異なるレート制限があります:

  • フリーティア:1分あたり6,000リクエスト、1日あたり約2百万トークン
  • 有料:プラン次第で異なります

無料枠を超える場合は、支払いプランにアップグレードしてください。 :::


Q3: 400 エラー(Bad Request)- リクエスト形式が不正

原因

モデル名のタイプミス、必須フィールドが不足、または無効なパラメータが含まれています。

解決法

ステップ1:モデル名を確認

# ❌ 間違ったモデル名
response = client.messages.create(
    model="claude-opus",  # ❌ バージョンなし
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}]
)
 
# ✅ 正しいモデル名
response = client.messages.create(
    model="claude-opus-4-1",  # または claude-sonnet-4-20250514
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}]
)

利用可能なモデル一覧:

- claude-opus-4-1(フル機能、最高性能)
- claude-sonnet-4-20250514(バランス型)
- claude-haiku-4-5-20251001(高速、軽量)

ステップ2:必須フィールドを確認

# ✅ 必須フィールド
response = client.messages.create(
    model="claude-opus-4-1",           # 必須
    max_tokens=1024,                   # 必須
    messages=[                         # 必須
        {"role": "user", "content": "Hello"}
    ]
)
 
# ❌ 必須フィールド不足の例
response = client.messages.create(
    model="claude-opus-4-1"
    # max_tokens を指定していない → エラー
)

ステップ3:パラメータ値を確認

# ❌ 無効なパラメータ値
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=0,              # ❌ 0 は無効(最小値は1)
    temperature=-0.5,          # ❌ 負の値は無効(0.0~1.0)
    top_p=1.5,                 # ❌ 1.0を超える値は無効
    messages=[{"role": "user", "content": "Hello"}]
)
 
# ✅ 有効なパラメータ値
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,           # 1~200000
    temperature=0.7,           # 0.0~1.0
    top_p=0.9,                 # 0.0~1.0
    messages=[{"role": "user", "content": "Hello"}]
)

ステップ4:メッセージ形式を確認

# ❌ 間違ったメッセージ形式
messages = [
    "Hello, Claude!"  # ❌ 文字列だけではダメ
]
 
# ✅ 正しいメッセージ形式
messages = [
    {
        "role": "user",        # "user" または "assistant"
        "content": "Hello, Claude!"  # 文字列またはコンテンツブロック
    }
]
 
# ✅ 複雑なコンテンツの例
messages = [
    {
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": "What's in this image?"
            },
            {
                "type": "image",
                "source": {
                    "type": "base64",
                    "media_type": "image/jpeg",
                    "data": "base64-encoded-image-data"
                }
            }
        ]
    }
]

ステップ5:エラーメッセージの詳細を確認

try:
    response = client.messages.create(
        model="claude-opus-4-1",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello"}]
    )
except anthropic.BadRequestError as e:
    print(f"Error type: {e.error}")
    print(f"Error message: {e.message}")
    print(f"Request: {e.request}")
    # エラーメッセージに詳細情報が含まれます

:::warning API リファレンスで各パラメータの許可値を確認してください。特に max_tokens の範囲とモデルごとの制限に注意。 :::


Q4: レスポンスが空、または max_tokens が小さすぎる

原因

max_tokens の値が小さすぎてレスポンスが切り詰められた、または応答にデータが含まれていません。

解決法

ステップ1:max_tokens を確認

# ❌ max_tokens が小さすぎる例
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1,  # ❌ 文字数がほぼ0
    messages=[{"role": "user", "content": "Write a 500 word essay"}]
)
# 結果:ほぼ空のレスポンス
 
# ✅ 適切な max_tokens
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=2048,  # 一般的な値
    messages=[{"role": "user", "content": "Write an essay"}]
)

ステップ2:レスポンスが完全であるか確認

response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}]
)
 
# レスポンスの完全性を確認
if response.stop_reason == "end_turn":
    print("✓ レスポンス完全")
elif response.stop_reason == "max_tokens":
    print("❌ max_tokens に達して切り詰められた")
    # max_tokens を増やす必要があります
else:
    print(f"Stop reason: {response.stop_reason}")

ステップ3:レスポンス内容を確認

# レスポンスが空でないか確認
if response.content:
    text = response.content[0].text
    print(f"Length: {len(text)} characters")
else:
    print("レスポンスが空です")
 
# 完全なレスポンス構造を確認
print(f"Stop reason: {response.stop_reason}")
print(f"Usage: {response.usage}")
print(f"Content blocks: {len(response.content)}")

ステップ4:プロンプトを確認

# ❌ 曖昧なプロンプト
messages = [{"role": "user", "content": ""}]
 
# ✅ 明確なプロンプト
messages = [{"role": "user", "content": "以下の Python コードについて説明してください:[code]"}]

:::tip モデルごとのコンテキストウィンドウ制限:

  • Claude Opus 4.1:200,000トークン
  • Claude Sonnet 4:200,000トークン
  • Claude Haiku:200,000トークン

max_tokens はコンテキストウィンドウ内に収まるよう設定してください。 :::


Q5: ストリーミングが動作しない、または部分的なレスポンスしか返らない

原因

ストリーミングの実装が不正、ネットワーク接続が切断、またはリクエストが不完全です。

解決法

ステップ1:ストリーミングの基本的な実装

Python の例:

import anthropic
 
client = anthropic.Anthropic()
 
# ✅ ストリーミングを有効にしたリクエスト
with client.messages.stream(
    model="claude-opus-4-1",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude!"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
 
print()  # 改行

Node.js の例:

import Anthropic from "@anthropic-ai/sdk";
 
const client = new Anthropic();
 
const stream = await client.messages.stream({
  model: "claude-opus-4-1",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello, Claude!" }],
});
 
for await (const chunk of stream) {
  if (
    chunk.type === "content_block_delta" &&
    chunk.delta.type === "text_delta"
  ) {
    process.stdout.write(chunk.delta.text);
  }
}

ステップ2:ストリーミングのエラー処理

# エラーハンドリング付きストリーミング
try:
    with client.messages.stream(
        model="claude-opus-4-1",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello"}]
    ) as stream:
        full_response = ""
        for text in stream.text_stream:
            full_response += text
            print(text, end="", flush=True)
 
        # ストリーム完了後に最終データを確認
        final_message = stream.get_final_message()
        print(f"\nStop reason: {final_message.stop_reason}")
 
except anthropic.APIError as e:
    print(f"Stream error: {e}")

ステップ3:タイムアウト設定

# タイムアウト付きストリーミング
client = anthropic.Anthropic(timeout=60.0)  # 60秒
 
try:
    with client.messages.stream(
        model="claude-opus-4-1",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Hello"}]
    ) as stream:
        for text in stream.text_stream:
            print(text, end="", flush=True)
except anthropic.APITimeoutError:
    print("Request timed out after 60 seconds")

ステップ4:ネットワーク接続を確認

# API エンドポイント への接続テスト
curl -I https://api.anthropic.com
 
# 200 OK が返ればネットワークは正常

:::warning ストリーミング中は以下に注意:

  • バッファサイズが大きすぎるとメモリを消費
  • 長時間のストリーミングはタイムアウトの可能性
  • flush() でバッファをクリアしてリアルタイム表示 :::

Q6: Tool use のレスポンス形式が不正、または期待と異なる

原因

tool_use パラメータの形式が不正、tool_choice の設定が不適切、またはツール定義が不完全です。

解決法

ステップ1:ツール定義を確認

# ✅ 正しいツール定義
tools = [
    {
        "name": "calculator",
        "description": "数値を計算するツール",
        "input_schema": {
            "type": "object",
            "properties": {
                "operation": {
                    "type": "string",
                    "enum": ["add", "subtract", "multiply", "divide"],
                    "description": "実行する操作"
                },
                "x": {
                    "type": "number",
                    "description": "最初の数値"
                },
                "y": {
                    "type": "number",
                    "description": "2番目の数値"
                }
            },
            "required": ["operation", "x", "y"]
        }
    }
]

ステップ2:tool_use を含むリクエスト

# ✅ ツール使用を含むリクエスト
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "5 + 3 は何ですか?"}
    ]
)
 
# レスポンスにツール呼び出しが含まれるか確認
for block in response.content:
    if block.type == "tool_use":
        print(f"Tool: {block.name}")
        print(f"Input: {block.input}")

ステップ3:tool_choice を設定

# ツール使用の挙動を制御
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    tools=tools,
    tool_choice={
        "type": "auto"  # ツール使用を自動判定
    },
    messages=[{"role": "user", "content": "計算してください"}]
)
 
# または特定のツールを強制使用
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    tools=tools,
    tool_choice={
        "type": "tool",
        "name": "calculator"  # このツールを使用するよう強制
    },
    messages=[{"role": "user", "content": "計算してください"}]
)

ステップ4:ツール結果をループバック

messages = [
    {"role": "user", "content": "15 + 20 を計算してください"}
]
 
while True:
    # API 呼び出し
    response = client.messages.create(
        model="claude-opus-4-1",
        max_tokens=1024,
        tools=tools,
        messages=messages
    )
 
    # アシスタント応答をメッセージに追加
    messages.append({"role": "assistant", "content": response.content})
 
    # ツール呼び出しがあるか確認
    tool_calls = [block for block in response.content if block.type == "tool_use"]
 
    if not tool_calls:
        # ツール呼び出しがない場合は終了
        break
 
    # ツール実行結果をメッセージに追加
    for tool_call in tool_calls:
        # ツールを実行(ここでは簡略化)
        if tool_call.name == "calculator":
            result = eval(f"{tool_call.input['x']} {tool_call.input['operation']} {tool_call.input['y']}")
 
        messages.append({
            "role": "user",
            "content": [
                {
                    "type": "tool_result",
                    "tool_use_id": tool_call.id,
                    "content": str(result)
                }
            ]
        })
 
# 最終応答を取得
final_response = messages[-1]

:::warning ツール定義では以下に注意:

  • input_schema は JSON Schema に準拠する必要がある
  • required フィールドに必須プロパティをすべて指定
  • description フィールドは詳細に(Claude がツール選択時に参考にする) :::

Q7: Context window を超過したエラー

原因

入力テキストが長すぎて、モデルの最大コンテキストウィンドウを超えています。

解決法

ステップ1:エラーを確認

try:
    response = client.messages.create(
        model="claude-opus-4-1",
        max_tokens=1024,
        messages=[
            {"role": "user", "content": very_long_text}
        ]
    )
except anthropic.BadRequestError as e:
    if "context_length_exceeded" in str(e):
        print("Context window exceeded!")
        # 解決策:テキストを分割

ステップ2:テキストを分割

# ❌ 大きすぎるテキストを1つのリクエストで処理
long_text = "..." * 100000  # 非常に長い
 
# ✅ テキストを分割して処理
def process_large_text(text, chunk_size=10000):
    chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
    summaries = []
 
    for i, chunk in enumerate(chunks):
        response = client.messages.create(
            model="claude-opus-4-1",
            max_tokens=1024,
            messages=[
                {
                    "role": "user",
                    "content": f"このセクション {i+1}/{len(chunks)} を要約してください:\n{chunk}"
                }
            ]
        )
        summaries.append(response.content[0].text)
 
    return summaries

ステップ3:会話履歴を管理

# ✅ 会話履歴のサイズを制限
def manage_conversation_history(messages, max_messages=10):
    """最新のメッセージのみを保持"""
    if len(messages) > max_messages:
        # システムメッセージは保持、古いメッセージを削除
        system_msg = [m for m in messages if m.get("role") == "system"]
        recent_msg = messages[-(max_messages-len(system_msg)):]
        return system_msg + recent_msg
    return messages

ステップ4:コンテキストウィンドウを確認

# API レスポンスから使用トークン数を確認
response = client.messages.create(
    model="claude-opus-4-1",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}]
)
 
print(f"Input tokens: {response.usage.input_tokens}")
print(f"Output tokens: {response.usage.output_tokens}")
print(f"Total: {response.usage.input_tokens + response.usage.output_tokens}")

:::tip コンテキストウィンドウの目安:

  • Claude Opus 4.1:200,000トークン(約150万単語)
  • 日本語の場合、約100万字

大規模な文書処理の場合は、複数リクエストに分割することをお勧めします。 :::


Q8: 「tool_result could not be submitted」エラーで会話が止まる

原因

tool_use ブロックと tool_result ブロックの対応が崩れていることが、ほぼすべての原因です。具体的には、tool_use_id が一致していない、アシスタントの tool_use ターンを messages に積まずにいきなり tool_result を送っている、複数の tool_use があるのに一部の tool_result しか返していない、といったケースです。

Claude は「直前のアシスタント応答に含まれる tool_use と、次のユーザーターンの tool_result が1対1で揃っていること」を厳密に要求します。1つでも欠けると、リクエスト全体が拒否されます。

個人開発でツールを何本も束ねていると、結果の取りこぼしは特に起きやすくなります。ループ処理の中で1つだけ append を忘れる、といった形で紛れ込みます。

解決法

ステップ1:アシスタント応答をそのまま messages に積む

response = client.messages.create(
    model="claude-opus-4-1", max_tokens=1024, tools=tools, messages=messages
)
 
# response.content(tool_use ブロックを含む)を丸ごと積むのが要です
messages.append({"role": "assistant", "content": response.content})

tool_use ブロックを自分で組み立て直す必要はありません。返ってきた response.content をそのまま渡すのが、最も壊れにくい方法です。

ステップ2:すべての tool_use に tool_result を返す

tool_uses = [b for b in response.content if b.type == "tool_use"]
 
tool_results = []
for tu in tool_uses:
    try:
        output = run_tool(tu.name, tu.input)
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": tu.id,   # ← ここが一致していないと弾かれます
            "content": str(output),
        })
    except Exception as e:
        # 失敗しても tool_result は返す。is_error を立てるのが作法です
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": tu.id,
            "content": f"Error: {e}",
            "is_error": True,
        })
 
# 複数の結果は1つのユーザーメッセージにまとめて返します
messages.append({"role": "user", "content": tool_results})

ツールが3つ呼ばれたら、tool_result も3つ。1つでも欠けたまま送ると、このエラーになります。

:::warning よくある取りこぼし:

  • tool_use_id をタイプミス、または別の呼び出しの id を使っている
  • ツール実行が例外で落ちて tool_result を append し忘れる(→ is_error を立てて必ず返す)
  • tool_result の前にテキストブロックを差し込んでいる(content 配列は tool_result から始める) :::

Q9: 「Spanner temporarily unavailable」が突然返ってくる

原因

これはあなたのコードの問題ではありません。Anthropic 側のバックエンド(分散データベース層)が一時的に応答できない状態を示す、サーバー由来の一過性エラーです。529(Overloaded)や 500 系と同じく、時間をおけば回復します。

私自身、初めてこの表示を見たときは設定を疑って手が止まりましたが、原因はこちら側にありませんでした。リクエスト形式が正しい前提なら、リトライ設計を整えるだけで十分です。

解決法

ステップ1:一過性エラーとして指数バックオフで再試行

import time, random
import anthropic
 
def create_with_retry(client, max_retries=5, **kwargs):
    for attempt in range(max_retries):
        try:
            return client.messages.create(**kwargs)
        except (anthropic.InternalServerError, anthropic.APIStatusError) as e:
            msg = str(e).lower()
            transient = "spanner" in msg or "overloaded" in msg or "temporarily" in msg
            if not transient or attempt == max_retries - 1:
                raise
            # 指数バックオフ + ジッター(同時再試行の集中を避ける)
            wait = min(2 ** attempt, 30) + random.uniform(0, 1)
            time.sleep(wait)

ステップ2:すぐに叩き直さない 回復前に短い間隔で再試行を連打すると、かえって混雑を長引かせます。1回目は1〜2秒、その後2倍ずつ広げ、上限を設けるのが安全です。

:::tip 判断の目安:

  • Spanner temporarily unavailable / Overloaded / 500・529 → サーバー側の一過性。バックオフで再試行
  • 400・401・404 → こちらのリクエストの問題。リトライしても直りません

継続して頻発する場合は、Anthropic のステータスページで障害情報を確認してください。 :::


全体を振り返って

Claude API の初期設定エラーは、以下の9つのステップで解決できます:

  1. API キーが正しく設定されているか確認(401エラーの解決)
  2. リクエストの並行数を制限(429レート制限の解決)
  3. リクエスト形式を確認(400エラーの解決)
  4. max_tokens を適切に設定(空レスポンスの解決)
  5. ストリーミング実装を確認(ストリーミング失敗の解決)
  6. ツール定義を正確に記述(tool_use エラーの解決)
  7. テキストを分割して処理(context window の解決)
  8. tool_use と tool_result を1対1で揃える(tool_result submission エラーの解決)
  9. サーバー由来の一過性エラーはバックオフで再試行(Spanner temporarily unavailable の解決)

エラーが発生した場合は、エラーメッセージの全文を保存し、エラーコードを確認してください。ほとんどの初期設定エラーは、これらのチェックポイントのいずれかで解決します。

Happy coding with Claude API!

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API & SDK2026-06-16
予約実行が始まる前に、使うモデルが本当に応答するか1回だけ確かめる
設定したモデルが、夜間ジョブが動き出す前に消えていることがあります。引退・撤回・地域制限の3つを起動時の1回のプローブで見分け、適格なモデルへ実行設定を自動で書き換える設計を TypeScript の動くコードでまとめました。
API & SDK2026-06-15
Anthropic API のベータヘッダを一元管理し、機能の引退でバッチを止めない設計
anthropic-beta ヘッダを散らばったまま使うと、ベータ機能の引退や GA 昇格でバッチ全体が 400 で落ちます。ケイパビリティ登録簿と起動時プリフライトで、機能の世代交代に耐える小さな抽象化を実装します。
API & SDK2026-05-04
Claude API Pythonクライアントで最初によく出るエラー:初心者が詰まる7つのポイントと解決コード
Claude API Python SDKを使い始めた際に遭遇しやすい7つのエラーを、原因と修正コードをセットで解説。AuthenticationError・RateLimitError・BadRequestError・レスポンス解析ミスなど、初心者が詰まりやすいポイントを体系的にまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →