# Claude assistant prefill 400 エラー：非対応モデルと代替手段

> Claude Opus・Sonnet 4.6 以降と Fable 5 系は assistant で終わるリクエストを 400 で拒否します。代替は prefill の用途次第です。

- URL: https://blog.laozhang.ai/ja/posts/claude-opus-prefill-error-fix
- Published: 2026-10-05
- Updated: 2026-10-05
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ja/about)
- Topic: API ガイド
- Tags: Claude API, Claude Opus 5.5, prefill, structured outputs, トラブルシューティング

---
`This model does not support assistant message prefill. The conversation must end with a user message.` は、`messages` 配列の最後が `role: "assistant"` になっているリクエストを、それを受け付けないモデルに送ったときに返る 400 `invalid_request_error` です。拒否するのは Claude Opus 4.6 以降（Opus 5.5 まで）、Sonnet 4.6 以降（Sonnet 5.5 まで）、Fable 5 と Fable 5.1、Claude Mythos Preview で、Sonnet 4.5、Haiku 4.5 とそれ以前のモデルはまだ受け付けます。再送やパラメータの調整では直りません。最後の assistant メッセージをなくし、それが担っていた役目を別の仕組みに移すのが修正です。

何に移すかは、その assistant メッセージで何をしていたかで決まります。JSON の書き出しを固定していたなら `output_config.format`（structured outputs）、前置きを省かせていたならシステムプロンプト、途中で切れた回答の続きを書かせていたなら部分回答を含む user メッセージです。自分のコードではなく GitHub Copilot や opencode などのツールで出ている場合は、ツールの更新、モデルの切り替え、新しい会話での再開、開発元への報告が利用者側でできることです。

モデルの対応状況とリクエストの形は、2026年10月5日時点の Anthropic 公式ドキュメント（API エラー一覧、structured outputs、各モデルの移行ガイド）に基づきます。コードはドキュメントのリクエスト形に沿った例で、実行結果を示すものではありません。

## エラーの意味：messages の最後が assistant だと 400 になる

assistant メッセージのプリフィル（prefill）とは、リクエストの最後に `role: "assistant"` のメッセージを置き、Claude の回答の書き出しをこちらで決めておく使い方です。たとえば最後に `{` を置いて JSON から書き始めさせる、`analysis` のような XML の開始タグを置いて決まった形式で書かせる、といった用途で広く使われてきました。

Claude 4.6 以降のモデルはこの形を受け付けません。API が返すエラー本文は次のとおりです。

```json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "This model does not support assistant message prefill. The conversation must end with a user message."
  }
}
```

エラーになるのは、次のようなリクエストです。

```json
{
  "model": "claude-opus-5-5",
  "max_tokens": 1024,
  "messages": [
    {"role": "user", "content": "次のレビューを positive・negative・neutral のどれかに分類し、JSON で返してください：配送は早かったが箱が潰れていた"},
    {"role": "assistant", "content": "{\"label\": \""}
  ]
}
```

最後の `assistant` を取り除き、会話が user メッセージで終わるようにすればこのエラーは出なくなります。ただし、取り除いただけでは書き出しの固定がなくなるので、出力が JSON にならない、前置きが付く、といった別の問題が起きます。そこを下の「代替手段」で埋めます。

ゲートウェイやツールを通すと、同じ英文が別のエラーに包まれて届きます。LiteLLM では `litellm.BadRequestError: AnthropicException - ...`、GitHub Copilot 経由では `invalid_request_body` というコード付き、OpenRouter では表示が `Provider returned error` だけになり、ログを開くと上流の Anthropic がこの英文を返している、という報告があります。Databricks の Foundation Model APIs（FMAPI）では `HTTP 400 BAD_REQUEST` の中に同じ英文が入ります。表示が違っても、本文に `assistant message prefill` があれば同じ原因です。

## prefill を拒否するモデル：Opus・Sonnet 4.6 以降と Fable 5 系

API エラー一覧には「Claude 4.6 以降のモデルと Claude Mythos Preview は assistant メッセージの prefill をサポートしない」とあり、各モデルの移行ガイドが個別に同じことを書いています。

| モデル | 最後が assistant のリクエスト | 根拠 |
| --- | --- | --- |
| Claude Opus 4.6、4.7、4.8、Opus 5、Opus 5.5 | 400 で拒否 | Opus 5.5 移行ガイド：Opus 4.6 以降の Opus は Opus 5.5 を含めて 400 |
| Claude Sonnet 4.6、Sonnet 5、Sonnet 5.5 | 400 で拒否 | Sonnet 5.5 移行ガイド |
| Claude Fable 5、Fable 5.1 | 400 で拒否 | Fable 5.1 移行ガイド：Fable 5 から変更なし |
| Claude Mythos Preview | 400 で拒否 | API エラー一覧 |
| Claude Sonnet 4.5、Haiku 4.5、Opus 4.5 以前 | 受け付ける | Sonnet 5.5 移行ガイド、Opus 5.5 移行ガイド |

表は2026年10月5日時点の Anthropic 公式ドキュメントに基づきます。表にない新しいモデルも、「4.6 以降」の記述に当てはまる限り拒否側と考えてください。

Sonnet 4.5 や Haiku 4.5 に戻せばエラーは消えますが、これは時間稼ぎです。どのモデルがいつまで提供されるかは変わるので、戻す前にモデル一覧で提供状況を確かめ、並行して prefill をなくす作業を進めるほうが確実です。Opus 4.6 から 4.7 以降へ上げるときは、prefill のほかにもリクエストの決まりが変わります（[Claude Opus 4.7 vs Claude Opus 4.6：2026年、いまアップグレードすべきか](https://blog.laozhang.ai/ja/posts/claude-opus-4-7-vs-claude-opus-4-6)）。

## prefill の代替手段は「何のための prefill だったか」で決まる

prefill は一つの仕組みで複数の目的を兼ねていたので、代替も目的ごとに分かれます。Sonnet 5.5 移行ガイドは置き換え先を次のように整理しています。

| prefill でしていたこと | 典型的な prefill | 置き換え先 |
| --- | --- | --- |
| 出力形式を固定する | `{`、`[`、XML の開始タグ（`result` など） | structured outputs（`output_config.format`）。分類なら enum 付きの strict ツール（`tool_choice` は `auto`） |
| 前置きをなくす | `答え：` | システムプロンプトで「前置きなしで答える」と指示する |
| 不要な拒否を避ける | 回答の書き出しを先に書いておく | user メッセージで明確に指示する。多くはこれで足りる |
| 中断した回答の続きを書かせる | 途中までの回答 | 部分回答を user メッセージに入れて続きを頼む |
| 文脈を念押しする | 「前提を踏まえて回答します」など | 念押しを user ターンに書く |

![prefill の代替策 3 つ、output_config.format、システムプロンプト、strict tool use を比較した図。図中の対象モデル表記は Opus 4.6](https://blog.laozhang.ai/posts/ja/claude-opus-prefill-error-fix/img/strategy-comparison.webp)

### JSON で返させていた場合：output_config.format か strict tool use

`{` の prefill で JSON を始めさせていたコードは、structured outputs に置き換えるのが本命です。JSON Schema を `output_config.format` に渡すと、回答はスキーマに沿った JSON として text ブロックで返ります。prefill と違って、閉じ忘れや必須フィールドの欠落も起きません。ドキュメントのリクエスト形は次のとおりです。

```bash
curl https://api.anthropic.com/v1/messages \
  -H "content-type: application/json" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "次のレビューを分類してください：配送は早かったが箱が潰れていた"}
    ],
    "output_config": {
      "format": {
        "type": "json_schema",
        "schema": {
          "type": "object",
          "properties": {
            "label": {"type": "string", "enum": ["positive", "negative", "neutral"]},
            "reason": {"type": "string"}
          },
          "required": ["label", "reason"],
          "additionalProperties": false
        }
      }
    }
  }'
```

SDK を使うなら、`client.messages.parse()` がスキーマの変換と応答の検証をまとめて引き受けます。Python では Pydantic モデルを渡し、検証済みの結果を `response.parsed_output` から受け取ります。

```python
from typing import Literal

import anthropic
from pydantic import BaseModel


class Review(BaseModel):
    label: Literal["positive", "negative", "neutral"]
    reason: str


client = anthropic.Anthropic()

response = client.messages.parse(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "次のレビューを分類してください：配送は早かったが箱が潰れていた"}
    ],
    output_format=Review,
)
print(response.parsed_output)
```

TypeScript では Zod のスキーマを `@anthropic-ai/sdk/helpers/zod` の `zodOutputFormat()` で包み、`output_config.format` に渡します。Zod オブジェクトをそのまま渡す書き方や、`response.parsed` で読む書き方はドキュメントの形と違います。

```typescript
import Anthropic from "@anthropic-ai/sdk";
import { z } from "zod";
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";

const Review = z.object({
  label: z.enum(["positive", "negative", "neutral"]),
  reason: z.string(),
});

const client = new Anthropic();

const response = await client.messages.parse({
  model: "claude-opus-5-5",
  max_tokens: 1024,
  messages: [
    { role: "user", content: "次のレビューを分類してください：配送は早かったが箱が潰れていた" },
  ],
  output_config: { format: zodOutputFormat(Review) },
});
console.log(response.parsed_output);
```

置き換えるときの注意は四つあります。

- **API のパラメータ名は `output_config.format`**：以前のベータ版の `output_format` は非推奨で、ベータヘッダー `structured-outputs-2025-11-13` を付けないと 400 になります。上の Python 例の `output_format=Review` は `parse()` の引数で、SDK が送信時に `output_config.format` へ変換します。HTTP で直接送る場合や `messages.create()` では `output_config` を使います。
- **prefill と citations とは併用できない**：JSON outputs は message prefilling と非互換で、citations を有効にしたまま `output_config.format` を付けると 400 になります。
- **`parse()` を使わない場合の読み取り位置**：Opus 5.5 のように thinking が常に有効なモデルでは、`content` の先頭が thinking ブロックになることがあります。`content[0]` 決め打ちではなく、`type` が `text` のブロックを探して読みます。
- **対応モデル**：structured outputs の対応一覧には Fable 5.1／5、Mythos 5.1／5／Preview、Opus 5.5／5／4.8／4.7／4.6、Sonnet 5.5／5／4.6／4.5、Opus 4.5、Haiku 4.5 が並んでいます。prefill を拒否するモデルはすべて含まれます。

分類やツール呼び出しの引数を形にしたいなら、ツール定義に `strict: true` を付ける strict tool use も使えます。enum で選択肢を絞ったツールを用意すれば、`{"label": "` の prefill で選ばせていた処理を置き換えられます。JSON outputs と strict tool use は同じリクエストで併用できます。

ただし、ツール呼び出しを強制して形式を固定する方法は、新しいモデルでは prefill の代わりになりません。Opus 5.5、Sonnet 5.5、Fable 5.1 は `tool_choice` の `{"type": "any"}` と `{"type": "tool", "name": "..."}` を、prefill とは別の 400（`tool_choice: type "tool" and "any" are not supported for this model.`）で拒否し、`auto` と `none` しか受け付けません。Sonnet 5.5 移行ガイドによれば、それより前の Sonnet 5、Sonnet 4.6、Sonnet 4.5、Haiku 4.5 は強制を受け付け、Fable 5 も受け付けます。prefill をやめるついでに強制ツール呼び出しへ移すと、モデルを上げた時点でまた 400 になります。これらのモデルでは `tool_choice: {"type": "auto"}` にしてツールに `strict: true` を付けるか、JSON outputs を使います。`auto` ではモデルがツールを呼ばずに答えることもあるので、どんなときにツールを使うかをプロンプトで指示します。

### 前置きを省かせていた場合・拒否を避けていた場合：指示で置き換える

`答え：` のような prefill で「はい、承知しました」などの前置きを消していたなら、システムプロンプトに「前置きや確認の言葉を付けず、答えから書き始める」と書きます。回答の書き出しを先に書いて不要な拒否を避けていた場合も、Sonnet 5.5 移行ガイドは user メッセージで明確に指示すれば多くは足りるとしています。

```python
import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=1024,
    system="前置き、言い換え、確認の言葉を付けず、答えの1文目から書き始めてください。",
    messages=[
        {"role": "user", "content": "このエラーログの原因を1文で教えてください：..."}
    ],
)
text = next(block.text for block in response.content if block.type == "text")
print(text)
```

文脈の念押し（「ここまでの前提を踏まえて答えます」のような prefill）も同じで、念押しの内容を最後の user ターンに書き足します。

### 途中で切れた回答の続き：部分回答を user メッセージに入れる

`max_tokens` やストリームの中断で切れた回答を assistant メッセージとして末尾に置き、続きを書かせる方法は、prefill を拒否するモデルでは使えません。Sonnet 5.5 移行ガイドの例は「Your previous response was interrupted and ended with `[previous_response]`. Continue from where you left off.」で、切れた部分を user メッセージの中に入れて続きを頼む形です。日本語で書いても考え方は同じです。

```python
def continuation_messages(history, partial, tail_chars=800):
    """history は user メッセージで終わる元の会話、partial は途中で切れた回答。"""
    tail = partial[-tail_chars:]
    return history + [{
        "role": "user",
        "content": (
            "前の回答は途中で中断され、次の文で終わっています。\n"
            f"<previous_response>{tail}</previous_response>\n"
            "この続きから書いてください。すでに書いた部分は繰り返さないでください。"
        ),
    }]
```

返ってきた続きは、手元で `partial` の後ろにつなげます。つなぎ目で文が重なることがあるので、結合前に確認してください。

### コード全体を一度に移行する：公式の移行スキル

prefill がコードのあちこちにあるなら、Opus 5.5、Sonnet 5.5、Fable 5.1 の各移行ガイドが紹介している、Claude Code 同梱の Claude API スキルが使えます。ガイドの例は Claude Code で `/claude-api migrate this project to claude-opus-5-5` と実行する形で、モデル ID の置き換え、互換性のないパラメータの変更、prefill の置き換え、effort の調整を必要に応じてコードベース全体に適用し、手で確かめる項目のチェックリストを出します。編集の前に対象範囲（作業ディレクトリ全体、サブディレクトリ、ファイル指定）の確認があり、Amazon Bedrock と Claude Platform on AWS のクライアントも検出し、モデル ID の形式と機能の違いを合わせます。

![prefill の代替策を選ぶ判断フロー。スキーマどおりの JSON が必要か、ツール呼び出しを使うエージェントかで分岐し、システムプロンプト、output_config.format、両方の併用を示す図。図中の表記は Opus 4.6](https://blog.laozhang.ai/posts/ja/claude-opus-prefill-error-fix/img/migration-flowchart.webp)

## Claude in Amazon Bedrock では structured outputs が使えない

Bedrock で Claude を呼んでいる場合、`output_config.format` が使えるかどうかは統合の種類で変わります。structured outputs のドキュメントでは、旧来の「Amazon Bedrock (Opus 4.6 and earlier)」統合では Claude Opus 4.6、Sonnet 4.6、Sonnet 4.5、Opus 4.5、Haiku 4.5 で使える一方、新しい統合の「Claude in Amazon Bedrock」では使えないとされています（2026年10月5日時点）。

Claude in Amazon Bedrock で prefill をやめる場合は、JSON の形をツール定義の入力スキーマで指定するか、システムプロンプトと user メッセージの指示で形式を伝えます。strict tool use も structured outputs の一部なので、Sonnet 5.5 移行ガイドは Bedrock 上の Sonnet 5.5 について、`strict` を付けずに `tool_choice: {"type": "auto"}` で送り、いつツールを呼ぶかをプロンプトで伝え、ツールの入力をコード側で検証する方法を示しています。Bedrock で出る 400 にはこのエラー以外にも種類があるので、エラー本文ごとの切り分けは [AWS の Claude 400 エラー、メッセージ別の対処法](https://blog.laozhang.ai/ja/posts/aws-claude-400-error) を参照してください。

## ライブラリ経由の原因：続きの生成と空の assistant ターン

自分では prefill を書いていないのにこのエラーが出るなら、使っているライブラリが内部で assistant メッセージを末尾に足しています。公開されている修正や報告では、原因は次の二つに分かれます。

**一つ目は、続きの生成やフォールバックで部分回答を assistant メッセージとして足すパターンです。** LiteLLM のルーターは、ストリームの途中で別モデルにフォールバックするとき、それまでの部分回答を assistant メッセージとして末尾に付けて再開していました。そのため Sonnet 4.6 や Opus 4.6 以降が相手だと、フォールバックのたびに 400 になり、回復できるはずのタイムアウトがチェーン全体の失敗に変わります。2026年6月11日に出た修正 PR（#30242、2026年10月5日時点で未マージ）は、`sonnet-4-6` 系に `supports_assistant_prefill: false` を設定し、prefill 非対応のモデルでは部分回答を user メッセージに載せる方式に切り替える内容です。同じ PR は livekit/agents、crewAI、agno でも同種の不具合が報告されていると挙げています。Dyad も、続きを書かせる再試行で assistant メッセージを末尾に置いていた処理を、部分回答を含む user メッセージに置き換えました（PR #3027、2026年3月23日マージ）。

**二つ目は、会話履歴の末尾に空の assistant ターンが残り、新しい user 入力がないまま送ってしまうパターンです。** OpenClaw では、ハートビートやシステムイベントの後に履歴が assistant ターンで終わったまま送信される経路があり、この 400 が出ていました。修正（#69268、2026年5月1日マージ）は、新しい user 入力がなければ送信自体をしない、というものです。

自前のエージェントやチャットクライアントなら、API を呼ぶ直前に末尾を確かめる処理を一つ入れておくと、両方のパターンを防げます。

```python
def is_empty(content):
    if isinstance(content, str):
        return content.strip() == ""
    return all(
        block.get("type") == "text" and not block.get("text", "").strip()
        for block in content
    )


def ready_to_send(messages):
    """末尾の空の assistant ターンを落とし、user で終わらなければ送らない。"""
    msgs = list(messages)
    while msgs and msgs[-1]["role"] == "assistant" and is_empty(msgs[-1]["content"]):
        msgs.pop()
    if not msgs or msgs[-1]["role"] != "user":
        return None  # 新しい user 入力がないので API を呼ばない
    return msgs
```

`tool_result` は user ロールのメッセージで返すので、ツール実行後の会話もこのチェックを通ります。中身のある assistant メッセージで終わっている場合は、それを消すのではなく、上の「途中で切れた回答の続き」の形で user メッセージに移します。

## Copilot や opencode など、コードを直せないツールで出る場合

GitHub Copilot、opencode、Google Antigravity、Databricks、LibreChat のエージェント、OpenHands などで、Claude の Opus や Sonnet を選んだときにこのエラーが出るという報告が公開されています。ツールが内部で組み立てるリクエストの末尾が assistant になっているのが原因なので、利用者が設定で直せる部分はほとんどありません。

opencode の issue #13768（「This model does not support assistant message prefill / Github Copilot with Opus 4.6」）は2026年2月15日に立ち、60日間動きがなかったため2026年9月2日に自動でクローズされましたが、2026年10月2日にも Opus 5.5 で起きるというコメントが付いています。クローズ済みの表示は解決済みを意味しません。

利用者側でできるのは次の四つです。

1. **ツールを最新版に更新する**：会話の組み立て方が直れば、それで解消します。リリースノートで prefill や Opus・Sonnet 4.6 以降への対応を確認します。
2. **ツールが使うモデルを切り替える**：prefill を受け付ける Sonnet 4.5 や Haiku 4.5、または Claude 以外のモデルに変えると、このエラーは出なくなります。品質や提供状況との引き換えなので、修正が出るまでのつなぎです。
3. **新しい会話で始め直す**：特定の会話の履歴が assistant ターンで終わった状態から抜け出せない場合は、新しい会話にすると進むことがあります。
4. **開発元に報告する**：使っているモデル、ツールのバージョン、エラー全文を添えて報告します。上の opencode のように既存の issue があれば、そこに状況を追記します。

## ほかの 400 との見分け方：thinking ブロック、tool_result、temperature

Claude 4.6 以降に上げたときに出る 400 は、どれも `invalid_request_error` で、ステータスコードだけでは区別できません。決め手はメッセージ本文です。prefill のエラーは `The conversation must end with a user message.` で終わり、会話の終わり方だけを問題にしています。

| エラー本文の手がかり | 原因 | 直し方 |
| --- | --- | --- |
| `assistant message prefill` / `must end with a user message` | 最後のメッセージが assistant | 上の「代替手段」の節 |
| `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified | 直前の assistant メッセージの thinking ブロックを編集・並べ替え・除外して送り返した | 受け取ったブロックをそのまま返す |
| `"thinking.type.enabled" is not supported for this model.` | Claude 4.7 以降に手動の extended thinking を指定した | adaptive thinking と `output_config.effort` に切り替える |
| `tool_choice: type "tool" and "any" are not supported for this model.` | Opus 5.5、Sonnet 5.5、Fable 5.1 でツール呼び出しを強制した | `auto` と strict tool use、または JSON outputs に切り替える |
| tool_use に対応する tool_result がないという趣旨 | ツール呼び出しの結果を次の user メッセージで返していない | 各 `tool_use` に `tool_result` を対応させる |
| `temperature` や `top_p` を含むもの | Opus 4.7 以降で既定値以外のサンプリングパラメータを送った | パラメータを削除する |

二行目の thinking ブロックのエラーも「latest assistant message」に触れますが、こちらは assistant メッセージを送ったこと自体ではなく、thinking ブロックを書き換えたことが原因です。サンプリングパラメータの 400 は [Claude Opus 4.7 の temperature パラメータエラーは、数値調整ではなく削除で直す](https://blog.laozhang.ai/ja/posts/claude-opus-4-7-temperature-parameter) と [Claude Code で top_p deprecated? まず Opus 4.7 の新しい request rule を確認](https://blog.laozhang.ai/ja/posts/claude-code-top-p-deprecated) を参照してください。

表のどの 400 も、同じリクエストを再送して直ることはありません。opencode のエラー記録でもこの prefill エラーは `isRetryable: false` として扱われています。再試行で回復しうるサーバー側のエラーとの違いは [Claude APIの500 api_error対処法：再試行後も失敗する場合の扱い](https://blog.laozhang.ai/ja/posts/claude-api-internal-server-error) を参照してください。
