Claude Media
Claude Code --json-schemaエラーの直し方 — JSON Schema検証に落ちる原因

Claude Code --json-schemaエラーの直し方 — JSON Schema検証に落ちる原因

Claude Codeの--json-schemaフラグでJSON Schemaが弾かれる原因を、3段階のチェック順序とformatキーワードの扱いから解説します。v2.1.205での挙動変化つき。

このTipsでできること

claude -p--json-schemaを渡すと、Error: --json-schema is not a valid JSON Schemaで終了コード1になり、プロンプトが実行されずに止まることがあります。この記事では、このエラーが起きる3段階のチェック順序と、実際に多い原因、formatキーワードにまつわる誤解を解説します。エラーメッセージ自体に直し方のヒントが含まれているので、その読み方も扱います。

なぜ「is not a valid JSON Schema」が出るか

--json-schemaは非対話モード(claude -p)専用のフラグで、Claudeの応答を指定した構造に固定します。渡した値がJSON Schemaとして成立していないと、Claude Codeはプロンプトを一切実行せずに止まります。API呼び出しの前に検証が完結する設計です。他のClaude Codeのエラーとあわせて切り分けたい場合はよくあるエラー10選も参照してください。

Claude Codeは--json-schemaの値に対して、順番に3段階のチェックをかけます。

  1. JSONとしてパースできるか: 失敗するとError: --json-schema is not valid JSON
  2. パース結果がオブジェクトか: 配列や文字列を渡すとError: --json-schema must be a JSON object
  3. JSON Schemaとしてコンパイルできるか: ここで失敗するとError: --json-schema is not a valid JSON Schemaに続けて検証器の診断が付く

3番目のエラーメッセージの末尾には、具体的な診断が入ります。

Error: --json-schema is not a valid JSON Schema: data/type must be equal to one of the allowed values

コロンの後ろの文字列が検証器の診断そのもので、data/から始まるパスがスキーマ内のどの位置で失敗したかを示します。ネストしたプロパティで同じ間違いをした場合は、パスの部分がそのプロパティの位置(properties配下の階層)に置き換わるだけで、読み方は同じです。診断がschema too largeなら、ネストの深さと$refの再利用を減らすと解消します。

具体的な直し方

診断メッセージが指す箇所を直接修正するのが最短ルートです。よくあるつまずきは次の2つです。

  • typeのスペルミスや値違い: 下のように"str"と書くと弾かれます
  • ネストが深すぎる: 階層が深いスキーマはschema too large診断が出やすくなります
{"type":"str"}
{"type":"string"}

"str"はPythonの型名を流用した誤記で、JSON Schemaが許可するtypeの値("object" "array" "string" "number" "integer" "boolean" "null")には含まれません。値を"string"に直すだけで検証を通過します。

これとは別に、required配列にpropertiesで定義していないプロパティ名を書くケースがあります。これはJSON Schemaとしては有効なので--json-schemaの3段階チェックは通過し、エラーにはなりません。ただし診断でも捕捉されないため、実行後にstructured_outputの中身が期待した形にならないときは、requiredpropertiesの対応が一致しているかをあらためて目視で確認する必要があります。

最小構成から確認する手順が有効です。まず{"type":"object"}のような単純なスキーマで--json-schemaが通ることを確認し、そこからpropertiesrequiredを1つずつ足していくと、どの追加で壊れたかを特定できます。

claude -p "auth.pyから関数名を抽出して" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'

このコマンドが成功すると、レスポンスのstructured_outputフィールドに{"functions": [...]}形式のJSONが入ります。resultフィールドには通常のテキスト応答、structured_outputには検証済みの構造化データという役割分担です。

formatキーワードは検証エラーにならない

JSON Schemaのformatキーワード("format": "email"のような値の形式指定)を使ったスキーマは、--json-schemaの検証を通ります。Claude Codeはformat注釈として受け取るだけで、値の形式を強制しません。メールアドレス形式のバリデーションを期待してformat: "email"を書いても、実際に値がメール形式かどうかはチェックされない点に注意が必要です。

format以外にも、値の取りうる範囲をスキーマ自体で表現する方法はあります。取りうる値が決まっているフィールドなら"enum": ["low","medium","high"]のように候補を列挙し、決まった書式のテキストなら"pattern": "^[A-Z]{2}-\\d{4}$"のような正規表現で書いておく形です。ただしenumpatternがモデルの出力に対してどこまで強制力を持つかは公式ドキュメントに明記がないため、formatと同様に過信せず、実際の出力を確認しながら運用するのが安全です。

v2.1.205より前とどう変わったか

--json-schemaの検証ロジックは、Claude Code v2.1.205で大きく変わりました。

挙動v2.1.204以前v2.1.205以降
不正なスキーマを渡したときv2.1.204以前エラーなしで構造化されていない通常のテキストが返るv2.1.205以降Error: --json-schema is not a valid JSON Schemaで終了コード1、プロンプト自体が実行されない
formatキーワードを含むスキーマv2.1.204以前常に無効なスキーマとして扱われていたv2.1.205以降注釈として許可され、検証エラーにならない

v2.1.204以前は、スキーマが壊れていてもエラーが出ず黙って通常のテキスト応答に切り替わっていたため、CIやスクリプトでstructured_outputフィールドの有無を確認しないと壊れたスキーマに気づけませんでした。v2.1.205からは実行前に止まるので、CI上での失敗検知は早くなった一方、formatを含むスキーマをすでに使っていた場合は、それまで無効だった理由が変わった(検証エラーではなく別の原因で失敗していないか)を確認する価値があります。

claude -pはAgent SDKをCLIから呼び出す入口

claude -pAgent SDKをCLI経由で使う入口です。SDKの構造化出力ドキュメントでは、JSON Schemaはdraft-07として検証されると説明されています。Zodのようなスキーマライブラリはdraft 2020-12を既定で出力するため、Zodから変換したスキーマを渡す場合はtarget: "draft-7"を指定して生成し直す必要があります。新しいdraftのキーワードを使ったスキーマは、構文として正しくてもdraft-07の枠に収まらずコンパイルエラーになることがあります。

TypeScriptで書くならz.toJSONSchema(FeatureSchema, { target: "draft-7" })のようにターゲットを明示してから--json-schemaに渡す流れになります。ここを省略してZodの既定出力(draft 2020-12)をそのまま渡すと、スキーマの内容自体は正しくても検証器がdraft-07の枠組みで解釈できず、コンパイル段階で弾かれます。手書きでスキーマを書いている場合はdraftの指定漏れという概念自体が発生しませんが、既存のZodやPydanticのモデルから自動生成する運用に切り替えるときは、この変換ターゲットの指定が抜けやすいポイントです。

CIやスクリプトに組み込むときの注意点

--json-schemaはCIパイプラインやバッチスクリプトから呼び出す場面で使われることが多いフラグです。前述の通り検証は実行前に完結するため、壊れたスキーマを渡した場合はclaudeプロセスがAPI呼び出しに進む前に終了コード1で戻ります。トークン消費が発生する前に失敗するので、スキーマのタイポを繰り返し試すデバッグ中でもコストは膨らみません。schema too largeが出たときは、公式が案内しているとおりネストの階層と$refの再利用そのものを減らすのが直し方です。スキーマを分割して1回のリクエストで渡す構造を小さくするほうが確実です。

シェルスクリプトに組み込むときは、終了コードとレスポンスの両方をチェックする形が安全です。--output-format jsonと組み合わせた場合、成功時はstructured_outputフィールドに検証済みのJSONが入り、jqで取り出せます。

result=$(claude -p "auth.pyから関数名を抽出して" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}')
echo "$result" | jq '.structured_output'

複数のスキーマを切り替えて使うパイプラインでは、スキーマファイルを別ファイルに切り出し、--json-schema "$(cat schema.json)"のようにシェル変数として読み込む形も選択肢です。スキーマをコマンドライン引数に直接ベタ書きするより、バージョン管理と差分レビューがしやすくなります。スキーマファイルを分離しておけば、CIの実行前に一般的なJSON Schemaバリデータで単体チェックするステップも組み込みやすくなり、claudeの実行自体に到達する前に壊れたスキーマを検知できます。スキーマを複数のコマンドで使い回す構成なら、この単体チェックを共通のCIジョブに切り出しておくと、個々のスクリプト側での重複チェックを省けます。

よくある質問

エラーになったときの終了コードは

1です。claude -pをシェルスクリプトやCIから呼ぶ場合、$?で判定してリトライやアラートの分岐に使えます。

Python版・TypeScript版のAgent SDKでも同じメッセージが出ますか

検証の考え方(draft-07への準拠)は共通ですが、CLIの--json-schema is not a valid JSON Schemaという文言はClaude CodeのCLI固有です。Python/TypeScriptのSDKパッケージでは、スキーマ不正は各言語の例外やエラーオブジェクトとして届きます。

スキーマが大きすぎるとどうなりますか

診断がschema too largeになることがあります。ネストされたオブジェクトの階層を浅くし、$refの再利用そのものを減らすと解消しやすくなります。

事前にスキーマの妥当性を確認する方法はありますか

一般的なJSON Schemaのバリデータでdraft-07として検証しておくと、claudeを実行する前に気づけます。最小構成のスキーマから始めて段階的に複雑にしていく進め方も、どこで壊れたかの切り分けに役立ちます。

--output-format jsonを付けずに--json-schemaだけ渡すとどうなりますか

--json-schema--output-format jsonとセットで使います。構造化出力をstructured_outputフィールドとして受け取るための出力形式指定なので、片方だけを渡す使い方は公式の使用例にもありません。

まとめ

--json-schema is not a valid JSON Schemaは、渡したJSON SchemaがJSONとしてはパースできても、draft-07のJSON Schemaとしてはコンパイルできないときに出ます。エラーメッセージのコロン以降が検証器の診断そのもので、data/から始まるパスがスキーマ内のどの位置で失敗したかを示すので、まずそこを読むのが最短です。

押さえておきたいポイントは3つです。formatキーワードは注釈扱いで検証エラーの原因にはならないこと、v2.1.205からは不正なスキーマが実行前に止まるようになったこと、そしてZodのようなスキーマライブラリから変換する場合はdraft-07をターゲットに指定し直す必要があることです。この3つを把握しておけば、CIでの構造化出力運用でスキーマ関連のつまずきをかなり減らせます。構造化出力の実装手順Agent SDKの入門もあわせて確認してください。

この記事を共有:XはてブLinkedIn