メインコンテンツへスキップ

API 400 の role 未対応エラーを、システム指示を壊さず直す

L
9 分で読めますAPI トラブルシューティング

unsupported role は role contract mismatch です。param、final JSON、endpoint mapping、same-route smoke test で指示優先度を保って直します。

API 400 の role 未対応エラーを、システム指示を壊さず直す

API が 400 を返し、role 'system' is not supported on this model と出る場合、最初に疑うべきものは API キー、残高、リトライ回数ではありません。リクエストはメッセージ構造を検査するルートまで届いており、そのルートが最終的に送信された messages[n].role を拒否しています。これはロール契約の不一致です。

まずエラー本文の param を読み、SDK、フレームワーク、Azure deployment、互換 gateway、middleware を通過した後の最終 outbound JSON と照合します。修正では、システム指示の意味と優先度を保ち、その同じルートが受け付ける最も高い優先度の instruction surface へ移してください。

失敗の手がかり主な責任箇所最初の安全な修正検証
messages[n].role = systemendpoint、provider gateway、Azure deployment、adapter contract指示テキストを保持し、そのルートが許す instruction surface に写す同じルートの最小リクエストで role error が消える
developer が拒否されるAPI version、compatibility layer、framework route現在の Chat Completions ルートがその role を受けるか確認し、無理なら Responses instructions か route-specific mapping を使う同じ payload 形状が選んだルートで通る
tool または旧 function が失敗するtool-calling protocol の不一致その API が要求する tool message と call id の形に合わせるtool result が role error なしで受け付けられる
ソースコードにその role がないagent framework、prompt wrapper、middleware、SDK adapter最終 outbound JSON を記録し、注入された message を無効化または再マップするminimal repro と本番フローで同じ accepted role set を使う

ここで止まり、キー変更、quota 調整、timeout 変更、provider 切り替えに進まないでください。それらは不正なロール契約を直しません。完了条件は、同じ provider、base URL、endpoint、API version、model または deployment、SDK adapter、framework route で最小リクエストが通ることです。

エラー本文を読んでからコードを変える

この 400 で重要なのは自然文のエラーメッセージではなく、構造化されたエラーオブジェクトです。statustypecodemessage、そして param を保存します。parammessages[0].role を指すなら先頭メッセージ、別の index なら履歴、tool result、middleware が追加した message を疑います。

アプリのソースに書いた配列だけを見ても足りません。送信前に memory prompt、default system prompt、tool policy、retry wrapper、OpenAI-compatible adapter、gateway が配列を作り替えることがあります。HTTP に最も近い境界で、脱秘した最終 payload を記録してください。

{
  "endpoint": "POST /v1/chat/completions",
  "model": "example-model",
  "messages": [
    { "role": "system", "content": "[redacted instruction]" },
    { "role": "user", "content": "[redacted user task]" }
  ]
}

ログの目的は構造証明だけです。API key、Bearer token、cookie、顧客テキスト、非公開のシステム指示、ファイル本文、tool output は残しません。必要なのは endpoint、model または deployment、message index、role、そしてどの層が最終 payload を作ったかです。

unsupported role エラーの責任箇所を決めるロール契約マップ

習慣ではなく endpoint で修正を選ぶ

危ない修正は、system を一律に developer へ変えること、またはすべての指示を user に落とすことです。ロール対応は endpoint、API version、Azure deployment、provider gateway、SDK、framework adapter の組み合わせで変わります。

2026-05-21 時点で、OpenAI Responses には開発者指示を置くための上位 instructions があり、公式 Chat Completions には messages 配列と現在の公式ルートで使われる instruction-style role があります。ただしこれは公式 OpenAI ルートの契約であり、Azure、互換 gateway、古い adapter、provider の model alias にそのまま広げることはできません。

現在の公式 Chat Completions ルートが developer を受けるなら、修正は次のようになります。

{
  "model": "your-selected-model",
  "messages": [
    { "role": "developer", "content": "Follow the support triage rules." },
    { "role": "user", "content": "Classify this API error." }
  ]
}

Responses ルートなら、継続的な指示は instructions に置き、ユーザータスクは input へ送ります。

{
  "model": "your-selected-model",
  "instructions": "Follow the support triage rules.",
  "input": "Classify this API error."
}

互換 gateway が userassistant しか受けない場合でも、すぐに system 指示を user message に入れないでください。専用 instruction field、model option、adapter 設定、別 route がないか確認します。ない場合は、指示優先度を失う可能性を behavior change として扱います。

指示優先度を保つ payload 修復の前後比較

role ごとに直す場所を分ける

system が拒否される場合、修正の目的は system 指示の制御力を保つことです。公式 Chat Completions では developer、Responses では instructions、gateway では route-specific field になることがあります。普通の user message への降格は最後の手段であり、出力制御が弱くなることを記録してください。

developer が拒否される場合、古い compatibility layer、provider 側の旧 schema、または Azure/API version の組み合わせが原因になりやすいです。base URL と API version が違えば、クライアントコードがほぼ同じでもサーバーの role contract は変わります。

tool が拒否される場合は role 名だけでなく、tool-calling protocol 全体を見ます。tool call id、assistant 側の tool call、tool result message の形が現在の API と一致している必要があります。旧 function message は別分岐で、新旧を混ぜるとモデルが tool 対応でも role error になります。

role が null、欠落、大文字小文字違い、enum serialization のズレで壊れる場合は、client construction bug です。送信前にローカルで止めます。

const allowedRoles = new Set(["developer", "user", "assistant", "tool"]);
for (const [index, message] of messages.entries()) {
  if (!allowedRoles.has(message.role)) {
    throw new Error("Unsupported outbound role at messages[" + index + "].role");
  }
}

この検証は provider docs の代わりではありませんが、不正な payload を本番まで流さないための安全網になります。

フレームワークは見えない場所で role を足す

「自分のコードでは system を送っていない」という説明は、アプリ層だけなら正しいことがあります。agent framework、chat UI library、RAG wrapper、memory module、tracing middleware、provider adapter は、送信直前に messages 配列を完成させます。

確認するもの典型的な失敗
Agent frameworkdefault system prompt、memory prompt、tool policy、guardrail messageuser input の前に hidden system または developer が入る
SDK adapterOpenAI-compatible conversion、enum mapping、legacy tool supportrole 名が route の契約と違う形に変換される
Gatewayprovider mode、upstream route、model aliasgateway は受けるが upstream が role contract を拒否する
Azure routedeployment name、api-version、region、model family同じ payload が別 deployment では通る
Middlewareretry wrapper、prompt decorator、request loggerwrapper が毎回 instruction message を追加する

観測点は HTTP request に最も近い境界です。pre-framework object しか見ていないなら、サーバーが検査した artifact をまだ見ていません。脱秘済みの最終 JSON は index、role、endpoint、adapter path を示し、修正対象を絞ります。

同じルートで smoke test する

別ルートで成功しても、失敗したルートが直った証明にはなりません。同じルートとは、provider、base URL、endpoint、API version、model または deployment alias、SDK adapter、framework settings、tool protocol が同一であるという意味です。

最小テストは、失敗した role branch だけを残します。

curl "$BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-selected-model",
    "messages": [
      {"role": "developer", "content": "Answer in one sentence."},
      {"role": "user", "content": "Say ready."}
    ]
  }'

Azure から direct OpenAI へ変える、API version を変える、model alias を変える、framework を外す、prompt を短くする、これらを同時に行うと診断になりません。理想のテストは、修正後 payload が通るか、role contract ではない別エラーに変わるかのどちらかです。

最小テストが通った後、role logging を入れたまま本番に近い agent flow を一度走らせます。framework が systemdevelopertool、旧 function を再注入するケースをここで検出します。

エスカレーションには証拠を入れる

同じルートの最小再現がまだ落ちる場合、provider、Azure 管理者、gateway 担当、framework 作者へ渡す packet を作ります。エラー文だけでは弱く、相手は endpoint、version、adapter、request id を推測することになります。

含めるべきものは次の通りです。

  • 秘密情報とユーザーデータを除いた request JSON
  • 正確な base URL と path、または provider route 名
  • model、deployment、region、API version
  • SDK、framework、adapter、gateway の version
  • response body、status code、paramcode
  • request ID、correlation ID、gateway trace ID
  • minimal same-route repro と、試した一つの controlled repair

unsupported role のエスカレーション用 evidence packet

API key、Bearer token、private prompt、customer text、file content、tool output、秘密が写る screenshot は含めません。route が必要な role を受けないと確認されたら、正しい instruction surface を持つ endpoint へ移るか、adapter で優先度を保つか、fallback による behavior change を明記します。

復旧チェックリスト

  1. response body と failing param を保存する。
  2. framework と adapter 変換後の final outbound JSON を記録する。
  3. direct OpenAI、Azure、gateway、SDK、framework のどこが owner か分ける。
  4. instruction text をその route が支持する最優先 surface へ移す。
  5. tool と legacy function は instruction role と別に検証する。
  6. minimal same-route smoke test を走らせる。
  7. role logging を残したまま full workflow を再実行する。
  8. まだ失敗する場合だけ、sanitized packet でエスカレーションする。

この順序なら signal が濁りません。400 を消すためだけに system instruction を user message へ落として、後からモデル制御が弱くなる事故も避けられます。

よくある質問

API key が間違っているという意味ですか?

通常は違います。key が間違っていれば authentication の段階で失敗し、message role の検査まで進みません。このエラーは、ルートが payload を解析したうえで特定の role を拒否したという意味です。

system をすべて developer に置き換えればよいですか?

いいえ。developer は、それを受け付ける Chat Completions ルートでだけ有効です。Responses には instructions があり、Azure や互換 gateway には別契約があり得ます。

system instruction を user に入れても安全ですか?

最後の fallback としてのみ扱ってください。user message は通常、system、developer、top-level instructions と同じ優先度を持ちません。エラーは消えても挙動が変わる可能性があります。

framework upgrade の後に出るのはなぜですか?

default role mapping、hidden instruction message、tool protocol の変換が変わった可能性があります。アプリが framework に渡した object ではなく、final HTTP payload を見てください。

direct OpenAI では通るのに互換 provider で落ちます

それは provider route の契約差です。同じ payload、endpoint、model alias、provider trace を保存し、その route が受ける roles と tool message shapes を確認してください。

support ticket には何を入れるべきですか?

sanitized request JSON、endpoint、model または deployment、API version、SDK と framework の version、response body、param、request ID、minimal same-route repro を入れます。秘密情報とユーザーデータは除きます。

Share:

laozhang.ai

One API, All AI Models

AI Image

Gemini 3 Pro Image

$0.05/img
80% OFF
AI Video

Sora 2 · Veo 3.1

$0.15/video
Async API
AI Chat

GPT · Claude · Gemini

200+ models
Official Price
Served 100K+ developers
|@laozhang_cn|Get $0.1