「contained only whitespace」エラーの対処 — Claude Code非対話モード
空白だけのプロンプトはAPIに送られる前にClaude Codeが拒否します。-pとstream-jsonセッションで挙動が違う理由と、スクリプト側の対処をまとめました。
Input contained only whitespaceが出る条件
非対話モード(claude -p)でスペース・タブ・改行だけのプロンプトを渡すと、モデルに送信される前にClaude Codeが処理を止めます。プロンプト引数でも標準入力でも結果は同じで、次のエラーで終了します。
Error: Input contained only whitespace. Provide a prompt with text through stdin or as a prompt argument when using --print--input-format stream-json で動いている実行中のセッションやAgent SDKのセッションに、空白だけのメッセージを送った場合は事情が変わります。エラーで終了せず、モデルを呼ばずにそのターンだけを終えて、セッションは使える状態のままです。
この違いが、CIで気づける失敗と、気づきにくい失敗を分けます。
空白だけの入力が来た場所で結果が変わる
claude -p(引数・標準入力)
エラー文言を出して終了します。プロセスが終わるので、CIやスクリプトでは呼び出し側が失敗に気づけます。
stream-json・Agent SDKのセッション
案内メッセージとターンの結果テキストの両方に、次の文言が入ります。プロセスは終わらないため、監視を置かないと見逃します。
後者の文言は、エラー一覧ではコマンドラインエラーの同じ節にまとめて載っています。
Blank prompt — the message was only whitespace, so nothing was sent to the model.エラーの意味 — APIが可視文字のないメッセージを拒否する
Claude Codeがこの入力を送信前に止めているのは、Claude APIが可視文字を含まないメッセージを受け付けないためです。空白だけのメッセージを送っても、APIに拒否されるだけで意味のある応答は返りません。Claude Code側で先に弾くので、モデルへのリクエスト自体が発生しません。
空白入力まわりの変更の流れ
- v2.1.208CRLFと空白行でセッションが落ちる問題を修正
Windows式のSDKホストが送る、CRLFだけの行や空白だけの行で、stream-jsonの入力がセッションを終了させていました。このバージョンで修正されています。
- v2.1.229空白だけのメッセージを送信前に検出
APIの400エラーに頼らず、Claude Code側が原因を名指しして止めるようになりました。
- v2.1.287Windowsで標準入力がターミナルでないときの案内を追加
Windowsで
-pなしのまま標準入力がターミナルでない場合、理由を示して終了するようになりました。それまではRaw modeのエラーなどで失敗していました。
直し方
単発のclaude -p実行で出た場合
プロンプトに可視のテキストを含めるだけです。引数を渡す場合は、クオートの位置がずれて空文字列や空白だけになっていないかを確認します。
claude -p "現在のブランチの差分を要約して"パイプで渡している場合は、パイプの手前で中身が空になっていないかを先に確認します。
echo "現在のブランチの差分を要約して" | claude -pシェルスクリプトから変数や外部ファイルでプロンプトを組み立てている場合
このエラーが実運用で厄介なのは、CIジョブやラッパースクリプトが変数やファイルからプロンプトを組み立てているケースです。変数が意図せず空になったり、テンプレートの置換に失敗して空白しか残らなかったりすると、claude を呼び出した時点で初めて発覚します。呼び出し前に中身を検証しておけば、失敗の原因がスクリプト側かClaude Code側かをその場で切り分けられます。
PROMPT="$(cat prompt.txt)"
if [ -z "$(echo "$PROMPT" | tr -d '[:space:]')" ]; then
echo "prompt.txtの中身が空です" >&2
exit 1
fi
claude -p "$PROMPT"tr -d '[:space:]' で空白文字をすべて除去した結果が空文字列かどうかを見れば、改行やタブだけが残っているケースも含めて検出できます。
事前検証は3ケースに分けて書く
実運用のスクリプトでは、失敗パターンを1つの条件式にまとめず、原因ごとに分けておくと調査しやすくなります。想定すべきケースは3つです。
- 変数が未設定・空文字列:
PROMPT=""のまま呼び出してしまうケース。[ -z "$PROMPT" ]で単独に検出できます。 - 変数に改行やタブだけが残っている: テンプレートエンジンの出力が空行だけになっている場合など。
tr -d '[:space:]'を通してから空文字列かどうかを見ないと検出できません。 - 可視文字はあるが無意味な値が入っている:
{{PROMPT}}のようなプレースホルダーが未置換のまま残るケースです。可視文字があるので空白だけの入力にはならず、そのまま送信されます。プレースホルダー文字列の残存チェックを別に足す必要があります。
stream-jsonセッションやAgent SDKの中で出た場合
セッションが終了しないので、次のメッセージを送れば続行できます。問題は、案内メッセージを見逃すとClaudeが応答していないように見える点です。--include-partial-messages や結果テキストを監視している自動化フローでは、このメッセージが来たらメッセージ生成側の不具合を疑う分岐を用意しておくと、原因追跡が早まります。Agent SDKでユーザー入力をそのまま転送している構成なら、入力欄の前後の空白をトリムしてから送る実装にすると、この分岐に入る頻度を減らせます。
stream-jsonでは、1つのメッセージが改行で終わる1行のJSONでなければなりません。空白だけの文字列が来る前に、行の区切りが崩れていないかも見る価値があります。
送信側が本当に空白しか送っていないかを確かめるには、--replay-user-messages を使います。v2.1.289の claude --help では、このフラグは次のように表示されます。
claude --help --replay-user-messages Re-emit user messages from stdin back on
stdout for acknowledgment (only works
with --input-format=stream-json and
--output-format=stream-json)--input-format stream-json --output-format stream-json と組み合わせて実行すると、受け取ったユーザーメッセージが標準出力に再送出されます。送信側のログと突き合わせれば、途中の変換処理で本文が失われて空白だけになっていないかを切り分けられます。同じ --help には、--input-format が "text"(既定)と "stream-json" を取り、どちらも --print 専用だという説明が出ています。
Blank prompt検出時の自動化フロー
- 1
検出する
結果テキストまたは案内メッセージに
Blank promptの文言が含まれるかを監視します。 - 2
記録する
どのターンで起きたか、直前に送ろうとしたメッセージの生成元(テンプレート、外部API、入力欄)をログに残します。
- 3
再送するか止めるかを決める
外部APIのタイムアウトのような一時的な不具合ならリトライします。テンプレートの参照先が存在しないといった恒常的な不具合なら、フローを止めて人に通知します。
セッションがエラーで終了しないため、3つ目の分岐がないと、空白メッセージが送られ続けているのにフローだけが正常終了したように見えます。
隣接するエラー: Input must be providedとの違い
似た場面で出る別のエラーに「Input must be provided either through stdin or as a prompt argument when using --print」があります。原因が違うので混同しないでください。
| エラー文言 | 原因 |
|---|---|
Input contained only whitespace | 原因プロンプトが空白文字だけ(何かは渡っている) |
Input must be provided... | 原因プロンプトが何も渡っていない(引数も標準入力のパイプもない) |
Input must be providedが出る再現条件
後者は、標準出力がターミナルでない環境(リダイレクトされたコンソールやPowerShell ISEなど)で claude を引数なしで実行したときにも出ます。この場合Claude Codeは対話UIを起動できず、-p と同じ非対話モードで動こうとします。-p を指定していなくてもメッセージに --print の名前が出るのはそのためです。渡した覚えのないプロンプトを要求されて戸惑ったら、まずこのケースを疑ってください。
再現条件は2つです。
- 標準出力がターミナルでない環境で、プロンプト引数も標準入力のパイプもない: 対話UIが起動できないので非対話モードとして扱われ、プロンプトが無いためこのエラーになります。
-pを指定したが、引数もパイプもない:claude -pとだけ実行して標準入力に何も流していない場合です。どの環境でも同じエラーになります。
対処はどちらも、実ターミナルで claude を実行するか、claude -p "質問" や echo "質問" | claude -p のようにプロンプトを渡すことです。
標準入力まわりで空白エラーと取り違えやすい失敗
パイプで渡す構成では、中身が空白だけではないのに止まる失敗もあります。見分けるポイントは、エラー文言に「whitespace」が出るかどうかです。
入力が大きすぎる
claude -p に標準入力で渡せるのは10MBまでです。超えると、エラーメッセージを出して0以外の終了コードで終わります。大きなログを渡したいときは、内容をファイルに書き出し、プロンプトにはそのファイルのパスを書く形にします。
stream-jsonの区切りが崩れている
claude -p --input-format stream-json では、1通のメッセージが改行で終わる1行のJSONでなければなりません。改行なしで268,435,456文字を超える入力が来ると、次のエラーを標準エラーに出し、終了コード1で終わります。
Error: stream-json input carried over 256M characters with no newline. Each stream-json message must be a single newline-terminated JSON line: either the producer is not newline-terminating its messages, or one message exceeded this budget.通常のログやバイナリを誤ってパイプした場合に起きがちです。プレーンテキストを送りたいなら --input-format stream-json を外します。claude -p は標準入力のプレーンテキストを、既定でプロンプトとして読みます。v2.1.257より前は、この上限がなくメモリが膨らみ続けました。
標準入力そのものが読めない
親プロセスが入力側を切断しているなど、標準入力を読めない場合は、警告を標準エラーに出してコマンドラインのプロンプトで続行します。v2.1.211より前のWindowsでは、セッションが落ちるか、何も出力せずに終了していました。
-pなしで標準入力が端末ではない
-p を付けずに claude を起動したのに、標準入力がパイプやリダイレクトだと「Claude Code can't read the keyboard here」で始まるエラーになります。Windowsでは、この案内を出して終了コード1で終わります。macOSとLinuxでは /dev/tty から入力を読んで対話セッションを始め、パイプしたテキストを最初のプロンプトにします。/dev/tty を開けない場合だけ、同じ趣旨のエラーが出ます。
よくある質問
改行だけのプロンプトも空白扱いになるか
なります。スペース・タブ・改行だけで構成されたプロンプトが対象です。見た目には何も入力していなくても、改行コードだけが残っている場合はこれに当たります。
空白の前後に本文がある場合は問題ないか
問題ありません。判定はメッセージ全体が空白だけかどうかなので、可視文字が1文字でもあれば通常どおり送信されます。前後の空白をトリムするかどうかは任意です。
関連して確認したい設定
--bg と --print の併用エラーなど、非対話モードのフラグ周りでつまずきやすい点は--bgと--printの競合エラーの解決法にまとめています。CI環境から claude -p を呼び出す全体の構成はClaude CodeをGitHub Actionsに組み込む、Agent SDKでの最小実装はClaude Agent SDK入門を参考にしてください。