Nano Banana 2のthought_signatureエラー(400 INVALID_ARGUMENT)は、マルチターンAPIリクエストでモデルが前回のレスポンスで返したthought_signatureフィールドを省略した場合に発生します。Nano Banana 2(gemini-3.1-flash-image-preview)は拡張思考(Extended Thinking)を使用して暗号化された推論トークンを生成しており、同一会話内の後続リクエストにはこれらの署名を変更せずに含める必要があります。修正方法はシンプルです。各APIレスポンスからthoughtSignatureフィールドを抽出し、次のリクエストの会話履歴に含めて返すだけです。公式のGoogle Gen AI SDKのチャット機能を使用している場合は自動的に処理されますが、REST APIを直接呼び出している場合、OpenAI互換エンドポイントを使用している場合、またはDifyやn8nなどのプラットフォームを経由している場合は、手動で対応する必要があります。
Thought Signatureエラーとは何か?なぜNano Banana 2に必要なのか?
Nano Banana 2にマルチターンリクエストを送信した際、APIが400 INVALID_ARGUMENT: Unable to submit request because it has an invalid thought signature for content at index Nというエラーを返す場合、Gemini 3モデルファミリーで最も一般的かつ厄介なエラーの一つに遭遇しています。このエラーは、APIキーが間違っている、あるいはリクエストの形式が従来の意味で不正であることを意味するものではありません。これは、会話履歴からコンテキストの必要な部分が欠落しているために、モデルの内部推論チェーンが断絶したことを意味しています。
なぜこれが起こるかを理解するには、Gemini 3モデルが「思考」をどのように処理するかを知る必要があります。Nano Banana 2(モデルID:gemini-3.1-flash-image-preview、Google AIドキュメント、2026年3月)がリクエストを処理する際、出力を生成する前にモデルがレスポンスを計画するための内部推論ステップである拡張思考を実行します。この思考ステップはthought_signatureと呼ばれる暗号化された文字列を生成します。これは本質的にモデルの推論プロセスの圧縮された表現です。ビデオゲームのセーブデータのようなものと考えてください。モデルは次のターンで一貫した会話を続けるためにこのセーブデータが必要です。これがなければ、モデルは受け取った会話履歴が実際に生成したものと一致しているかを確認できず、400エラーでリクエストを拒否します。
多くの開発者がつまずく重要なポイントは、この署名がthinkingConfig: { thinkingBudget: 0 }を明示的に設定したり、思考を「オフ」にした場合でも生成されるということです。思考プロセスは内部で依然として実行され、署名は生成され続け、必要とされます。Googleの公式ドキュメントでは、思考の設定に関係なく思考トークンが常に課金されることが確認されています(ai.google.dev/thought-signatures、2026年3月)。これは多くの開発者を驚かせます。思考をオフにすれば署名フィールドを無視できると想定し、2ターン目で400エラーに遭遇するのです。会話型画像編集ワークフローの構築中にこのエラーに悩まされている方は、決してあなただけではありません。Dify(#2262)、CherryStudio(#11391)、n8n、OpenClaw(#5001)、Pipecat(#3557)のGitHub Issueはすべてこの同じ根本原因にたどり着きます。thought signature以外のNB2エラーの全体像については、Nano Banana 2の包括的なトラブルシューティングガイドをご覧ください。
Thought Signatureが必要な場合と不要な場合

コードベース全体でこのエラーを防ぐには、thought signatureを返す必要がある場合と、安全に無視できる場合を理解することが鍵となります。ルールはGemini 3とGemini 2.5モデルで異なり、さらにNano Banana 2の画像生成ユースケースでも異なります。この判断を誤ると、コードに不要な複雑さを加えるか、本番環境で予期しない400エラーに遭遇することになります。
Gemini 3モデル(gemini-3-flash-preview、gemini-3-pro-preview)では、すべての関数呼び出しシナリオでthought signatureが必須です。つまり、アプリケーションでGemini 3のツール使用や関数呼び出しを利用している場合、すべての後続ターンでthought signatureを抽出して返す必要があります。例外はありません。シーケンシャルな関数呼び出しは特に厄介で、シーケンスの各ステップが独自の署名を生成し、関数の結果を返す際にすべてを含める必要があります。パラレルな関数呼び出しは異なるパターンで、レスポンスの最初のfunctionCallパートのみが署名を持つため、そのひとつだけをキャプチャして返せばよいのです。関数呼び出しを伴わないプレーンテキストのマルチターン会話では、Gemini 3では署名は推奨されますが強制されません。つまり、省略しても400エラーは発生しませんが、Googleは最適なレスポンス品質のために含めることを推奨しています。
Gemini 2.5モデルでは、ルールはより緩和されています。Thought signatureは全面的に任意です。関数呼び出し、テキスト会話、すべてにおいてです。モデルは署名の有無に関わらずリクエストを受け付けます。ただし、Gemini 2.5とGemini 3の両方のモデルで動作するコードを構築している場合、最も安全なアプローチはモデルが返すものすべてを(署名を含めて)常に返すことです。
Nano Banana 2(gemini-3.1-flash-image-preview)は、主にマルチターンの画像生成・編集に使用されるため、特別なカテゴリに分類されます。画像を生成してからフォローアップターンで編集を依頼する場合、thought signatureは必須です。これは多くの開発者がこのエラーに遭遇する主なユースケースであり、関数呼び出しのシナリオよりもドキュメント化が不十分です。実用的なルールはシンプルです。NB2を使ったマルチターンワークフロー(画像の生成と改良、ビジュアルコンテンツに関する会話、画像編集の連鎖など)を構築する場合は、thought signatureを処理する必要があります。NB2の機能と他のモデルの詳細な比較については、Nano Banana Pro vs Nano Banana 2の比較をご覧ください。
マルチターン画像生成でのエラー修正
マルチターン画像編集はNano Banana 2の主要なユースケースであり、ほとんどの開発者がthought signatureエラーに初めて遭遇する場面です。ワークフローは単純明快で、画像を生成してからモデルに修正を依頼するだけですが、署名の処理は見落としやすい重要なステップを追加します。以下に、すべてのステップで署名抽出をハイライトした完全なフローを示します。
Google Gen AI SDKを使用したPython実装:
pythonimport google.generativeai as genai import base64 genai.configure(api_key="YOUR_API_KEY") model = genai.GenerativeModel("gemini-3.1-flash-image-preview") response = model.generate_content( "Generate a photo of a golden retriever playing in a park", generation_config=genai.GenerationConfig( response_modalities=["TEXT", "IMAGE"] ) ) # ステップ2: レスポンスからthought signatureと画像を抽出 thought_signature = None image_data = None text_response = "" for part in response.candidates[0].content.parts: if hasattr(part, "thought_signature") and part.thought_signature: thought_signature = part.thought_signature if hasattr(part, "inline_data") and part.inline_data: image_data = part.inline_data if hasattr(part, "text") and part.text: text_response += part.text print(f"Signature captured: {thought_signature[:30]}...") # ステップ3: 署名を含むマルチターン履歴を構築 history = [ # あなたの元のリクエスト {"role": "user", "parts": [{"text": "Generate a photo of a golden retriever playing in a park"}]}, # モデルのレスポンス — thought_signatureを必ず含める {"role": "model", "parts": []} ] # 署名付きでモデルのレスポンスパーツを再構築 for part in response.candidates[0].content.parts: part_dict = {} if hasattr(part, "text"): part_dict["text"] = part.text if hasattr(part, "inline_data") and part.inline_data: part_dict["inline_data"] = { "mime_type": part.inline_data.mime_type, "data": part.inline_data.data } if hasattr(part, "thought_signature") and part.thought_signature: part_dict["thought_signature"] = part.thought_signature history[-1]["parts"].append(part_dict) # ステップ4: 完全な履歴と共に編集リクエストを送信 edit_response = model.generate_content( contents=history + [ {"role": "user", "parts": [{"text": "Now add a red frisbee in the dog's mouth"}]} ], generation_config=genai.GenerationConfig( response_modalities=["TEXT", "IMAGE"] ) ) # ステップ5: さらなる編集に備えて新しい署名を抽出 new_signature = None for part in edit_response.candidates[0].content.parts: if hasattr(part, "thought_signature") and part.thought_signature: new_signature = part.thought_signature print(f"Edit successful! New signature: {new_signature[:30]}...")
重要なステップはステップ3にあります。会話履歴を再構築する際、モデルの前回のレスポンスには返された通りのthought_signatureフィールドを含める必要があります。これを削除したり、テキストと画像データだけにレスポンスを簡略化したり、すべてのパーツを走査し忘れたりすると、次のターンで400エラーが発生します。NB2からのすべての画像生成レスポンスには、パーツのどこかにthought signatureが含まれています。あなたの仕事はそれを忠実に保持することです。
TypeScript実装:
typescriptimport { GoogleGenerativeAI } from "@google/generative-ai"; const genAI = new GoogleGenerativeAI("YOUR_API_KEY"); const model = genAI.getGenerativeModel({ model: "gemini-3.1-flash-image-preview" }); // 最も簡単なアプローチ:チャットインターフェースを使用 const chat = model.startChat({ generationConfig: { responseModalities: ["TEXT", "IMAGE"] } }); // ターン1: 画像を生成(署名はSDKが自動処理) const result1 = await chat.sendMessage("Generate a photo of a sunset over mountains"); // ターン2: 画像を編集(SDKが署名を自動で受け渡し) const result2 = await chat.sendMessage("Add a silhouette of a person hiking"); // ターン3: さらに改良 const result3 = await chat.sendMessage("Make the colors more vibrant and add lens flare");
TypeScriptの例ではSDKのチャットインターフェースを使用しており、署名管理を自動的に処理します。このアプローチが使用可能であれば、thought signatureエラーのクラス全体を排除できます。SDKは内部ですべての署名を追跡し、手動操作なしで後続のリクエストに含めます。これはほとんどのアプリケーションにとって最も推奨されるアプローチです。NB2画像生成の料金詳細については、Nano Banana 2 API料金ガイドをご覧ください。
ストリーミング、並列呼び出し、OpenAI互換モードの対応

ストリーミングレスポンス、並列関数呼び出し、OpenAI互換モードはそれぞれ独自のthought signatureエッジケースを持ち、アプリケーションを静かに壊す可能性があります。ストリーミングのケースは特に厄介で、ストリームパーサーの動作方法とレスポンスストリームで署名が実際に出現する位置との間の微妙な相互作用が関係しています。
ストリーミング:空テキストパーツの罠
NB2やGemini 3モデルでストリーミングを使用する場合、thought signatureは最初のチャンクや予測可能な中間チャンクには到着しません。ストリームの最終チャンクに到着し、ここに罠があります。最終チャンクには空のテキスト文字列(text: "")と共にthought_signatureフィールドが含まれることが多いのです。ほとんどのストリーミングパーサーはif chunk.text:でチャンクを処理するかどうかを判断し、空文字列はほとんどの言語でfalseと評価されます。つまり、パーサーは署名を含む唯一のチャンクを静かにスキップし、次のターンで400エラーが発生します。
修正方法は、便利なプロパティに頼るのではなく、パーツを明示的にイテレーションすることです:
python# 間違い: 空テキストチャンクで署名を失う signature = None for chunk in response: if chunk.text: # 空文字列 = False = 署名が失われる! result += chunk.text # 正解: すべてのチャンクのすべてのパーツをチェック signature = None full_text = "" for chunk in response: for part in chunk.candidates[0].content.parts: if hasattr(part, "thought_signature") and part.thought_signature: signature = part.thought_signature if hasattr(part, "text") and part.text: full_text += part.text
このパターンは、署名がどのチャンクに含まれていても、付随するテキストパーツが空であっても、署名を確実にキャプチャします。パフォーマンスへの影響はごくわずかで、すでに処理しているはずのパーツをイテレーションしているだけですが、信頼性の向上は顕著です。
並列関数呼び出し
Gemini 3が単一のレスポンスで複数の関数呼び出しを返す場合(並列関数呼び出し)、最初のfunctionCallパートのみがthought signatureを持ちます。同じレスポンス内の後続の関数呼び出しパーツには独自の署名がありません。関数の結果を返す際には、最初の関数呼び出しパートからの署名をレスポンスに含める必要があります。これはGoogleの公式ドキュメントに記載されていますが、関数呼び出しの処理自体に集中していると見落としやすいポイントです。ループで関数呼び出しを処理して各関数から署名を抽出しようとすると、値を持つのは最初のものだけであることがわかります。その単一の署名が返すべきものです。
OpenAI互換モード
OpenAI互換エンドポイント(OpenAIからの移行時やゲートウェイサービスの利用時に一般的)を通じてGeminiモデルにアクセスしている場合、thought signatureはレスポンス内のまったく異なる場所に格納されています。パートレベルのthought_signatureの代わりに、メッセージオブジェクト内のextra_content.google.thought_signatureにネストされています。これは、OpenAIコードをGemini対応に移行中の多くの開発者を困惑させます。ネイティブGemini APIドキュメントに基づいて署名処理を実装しますが、OpenAI互換レイヤーはレスポンスの構造が異なるのです。修正方法は、互換モード使用時に代替フィールドパスをチェックすることです:
python# ネイティブGemini API signature = part.thought_signature # OpenAI互換モード signature = message.get("extra_content", {}).get("google", {}).get("thought_signature")
アプリケーションが複数のAPIモードをサポートしている場合、両方のパスを処理する必要があります。ネイティブと互換の両方のエンドポイントで動作する必要があるプロダクションアプリケーションには、署名抽出を両方の場所をチェックするヘルパー関数に抽象化することを推奨します。
高度な回避策 — ダミーシグネチャとモデル移行
Googleの公式ドキュメントに、他の記事では目立って取り上げられていない回避策が隠されています。ダミーthought signatureです。Gemini 3で生成されていない会話履歴がある場合(別のモデルからの移行、合成的な会話コンテキストの注入、署名を保存していないデータベースからの履歴再構築など)、実際の署名の代わりに特別なプレースホルダー文字列を使用できます。
Googleは署名バリデーターをバイパスする2つの公式ダミー署名文字列を提供しています(ai.google.dev/thought-signatures FAQ、2026年3月):
python# オプション1: 推奨ダミー署名 dummy_signature = "context_engineering_is_the_way_to_go" # オプション2: 代替ダミー署名 dummy_signature = "skip_thought_signature_validator"
これらの文字列のいずれかを会話履歴内のモデルターンのthought_signature値として含めると、APIはバリデーションなしで受け付けます。これはいくつかのシナリオで非常に有用です。GPT-4やClaudeからGemini 3への既存会話履歴の移行、thought signatureの保存を想定していないデータベースからの会話復元、モデルを通過しなかったシステムレベルのコンテキストターンの注入、実際の署名なしでのマルチターンワークフローのテストなどです。
ただし、本番環境でダミー署名に依存する前に理解しておくべき重要な注意点があります。ダミー署名はモデルに対して、関連するターンの思考コンテキストが利用できないことを伝えます。つまり、モデルはそのターンの推論の一貫性を検証できません。Gemini 3の関数呼び出しワークフローでは、モデルが元の推論チェーンを参照できないため、レスポンス品質がわずかに低下する可能性があります。NB2の画像編集に限って言えば、画像生成ターンにダミー署名を使用すると、モデルが行ったクリエイティブな判断を完全に「記憶」できない可能性があり、後続の編集の品質に影響する場合があります。ダミー署名アプローチは、適切な署名管理の恒久的な代替としてではなく、移行ツールやフォールバックとして最適に機能します。
実用的な意思決定ツリーは明確です。実際の署名を抽出して保存できる場合は、常にそうしてください。署名のないレガシー履歴がある場合は、すべての会話履歴をゼロから再構築するのではなく、ダミー署名を使用して移行のブロックを解除してください。プロトタイピングやテスト中であれば、ダミー署名により署名の配管を気にせずビジネスロジックに集中できます。
プラットフォーム別修正:Dify、CherryStudio、n8nなど

thought signatureエラーは単なる生のAPIの問題ではありません。AI開発プラットフォームやツール全体に広がる問題でもあります。Gemini 3モデルをDify、CherryStudio、n8n、または同様のプラットフォームを通じて使用する場合、プラットフォーム内部のメッセージ処理が会話ターン管理中にthought signatureを削除したり失ったりすることがよくあります。これは、完全に正しいAPI認証情報とモデル設定を持っていても、プラットフォームが認識していないフィールドを静かに削除しているため、400エラーが発生する可能性があることを意味します。
Difyは現在最も影響を受けているプラットフォームです。Difyのメッセージ履歴管理は、モデルのレスポンスから非標準フィールドを保存前に削除し、thought_signatureは非標準フィールドとして扱われます。これにより、Gemini 3モデルとのマルチターン会話は最初のターン以降一貫して失敗します。この問題はGitHub Issue #2262で追跡されており、修正するプルリクエストがレビュー待ちです。当面の回避策は、Difyの組み込みGemini統合をバイパスし、HTTP Requestノードを使用して独自の会話履歴管理でGemini APIを直接呼び出すことです。セットアップは増えますが、リクエストとレスポンスのペイロードを完全に制御できます。
CherryStudioにはより微妙な問題があります。デスクトップクライアントは通常の会話フローではthought signatureを保持しますが、「再生成」ボタンを使用すると失われます。CherryStudioがレスポンスを再生成する際、再生成されるターンの元の署名なしで会話履歴を再構築し、400エラーが発生します。回避策は簡単です。再生成を使用せず、代わりに新しい会話を開始するか、メッセージを新しいターンとして言い換えてください。この問題はGitHub Issue #11391で追跡されています。
n8nはDifyと同じ根本的な問題に直面しています。GeminiノードがワークフローのExecution間で会話状態にthought signatureフィールドを保持しません。n8nユーザーには、Gemini専用ノードの代わりにHTTP Requestノードを使用し、APIペイロードを直接制御することを推奨します。n8nのワークフローデータに完全なレスポンス(署名を含む)を保存し、後続のターンで手動で会話履歴を再構築できます。
LangChainはバージョン0.3.x以降でこの問題をすでに修正しています。古いバージョンを使用している場合、最新リリースに更新するとthought signatureの処理が自動的に解決されます。LangChainのChatGoogleGenerativeAIクラスは、会話履歴の構築時にthought signatureを含むすべてのレスポンスメタデータを保持するようになりました。
OpenClawやGeminiモデルのOpenAI互換エンドポイントを提供するその他のAPIゲートウェイサービスには異なる問題があります。OpenAI互換レスポンスからextra_content.google.thought_signatureフィールドを転送しない場合があります。回避策は、OpenAI互換エンドポイントの代わりにゲートウェイを通じてネイティブGemini APIエンドポイントを使用するか、すべてのレスポンスフィールドを保持するようゲートウェイを設定することです。
すべてのプラットフォームに対する汎用的なフォールバックは、前のセクションで説明したダミー署名の回避策です。プラットフォームが実際の署名を削除する場合、前述の品質に関する注意点はあるものの、会話を継続させるために会話履歴の署名値として"context_engineering_is_the_way_to_go"を注入できます。
本番環境対応のThought Signatureハンドラー
画像編集、関数呼び出し、ストリーミング、複数のAPIモードにわたるすべてのシナリオで堅牢なthought signature処理が必要な本番アプリケーション向けに、このガイドでカバーしたすべてのエッジケースをカプセル化した再利用可能なハンドラークラスを以下に示します。
pythonclass ThoughtSignatureHandler: """マルチターンGemini会話におけるthought signatureを管理します。""" DUMMY_SIGNATURES = [ "context_engineering_is_the_way_to_go", "skip_thought_signature_validator" ] def __init__(self): self.signatures = {} # turn_index -> signature def extract_from_response(self, response, turn_index: int) -> str | None: """Gemini APIレスポンスからthought signatureを抽出します。""" sig = None if hasattr(response, "candidates") and response.candidates: for part in response.candidates[0].content.parts: if hasattr(part, "thought_signature") and part.thought_signature: sig = part.thought_signature break if sig: self.signatures[turn_index] = sig return sig def extract_from_stream(self, stream, turn_index: int): """ストリーミングレスポンスから署名を抽出し、チャンクをyieldします。""" sig = None for chunk in stream: if hasattr(chunk, "candidates") and chunk.candidates: for part in chunk.candidates[0].content.parts: if hasattr(part, "thought_signature") and part.thought_signature: sig = part.thought_signature yield chunk if sig: self.signatures[turn_index] = sig def extract_from_openai_compat(self, message: dict, turn_index: int) -> str | None: """OpenAI互換レスポンス形式から署名を抽出します。""" sig = (message.get("extra_content", {}) .get("google", {}) .get("thought_signature")) if sig: self.signatures[turn_index] = sig return sig def get_signature(self, turn_index: int, fallback_dummy: bool = False) -> str | None: """ターンの保存済み署名を取得し、オプションでダミーにフォールバックします。""" sig = self.signatures.get(turn_index) if sig is None and fallback_dummy: return self.DUMMY_SIGNATURES[0] return sig def build_history_part(self, part_data: dict, turn_index: int) -> dict: """モデルのレスポンスパーツにthought signatureが含まれることを保証します。""" sig = self.signatures.get(turn_index) if sig and "thought_signature" not in part_data: part_data["thought_signature"] = sig return part_data
このハンドラーは3つの主要な抽出シナリオ(標準レスポンス、ストリーミング、OpenAI互換)をカバーし、ターンインデックスごとに署名を保存し、実際の署名が利用できない場合のダミー署名へのフォールバックを提供します。extract_from_streamメソッドは、署名を含むチャンクから透過的に署名をキャプチャしながらチャンクをyieldするジェネレーターです。処理ロジックを変更することなく、既存のストリーミングコードに組み込むことができます。
TypeScriptアプリケーションの場合、SDKのチャットインターフェースを使用できるため、同等のパターンはさらにシンプルです。TypeScriptで生のREST呼び出しを使用する必要がある場合は、オプショナルチェーンを使用して同じ抽出ロジックを適用してください:
typescriptconst extractSignature = (response: any): string | undefined => { return response?.candidates?.[0]?.content?.parts ?.find((p: any) => p.thoughtSignature)?.thoughtSignature; };
本番システムを構築する際は、NB2には厳格なレート制限があり、署名エラーと組み合わさると混乱する障害モードを生む可能性があるため、署名管理と並行してレート制限処理も実装することを検討してください。詳細については、Nano Banana 2のレート制限完全ガイドをご覧ください。NB2画像生成のスループット向上やレート制限の緩和が必要なチームには、laozhang.aiが競争力のある価格でAPIアクセスを提供しています(標準の約$0.067/画像(1Kトークン)に対して$0.05/画像)。
FAQ — Thought Signatureに関するよくある質問
Nano Banana 2は常にレスポンスにthought_signatureを返しますか?
はい。NB2およびその他のGemini 3モデルからのすべてのレスポンスには、思考が「オフ」に設定されていたりthinkingBudgetが0であっても、thought signatureが含まれます。思考プロセスは常に内部で実行され、署名は常に生成されます。署名の生成をオプトアウトすることはできません。返すかどうかを選択できるだけであり(常に返すべきです)。
間違った署名や別の会話からの署名を使用するとどうなりますか?
同じ400 INVALID_ARGUMENTエラーでAPIがリクエストを拒否します。署名はそれを生成した特定の会話ターンに暗号的に結び付けられています。会話間や同一会話内のターン間で署名を交換することはできません。各ターンの署名は、それが生成された正確な位置で正確に1回だけ使用する必要があります。
公式のGoogle Gen AI SDKはthought signatureを自動的に処理しますか?
はい、SDKのチャットインターフェース(TypeScriptのmodel.startChat()またはPythonのmodel.start_chat())を使用する場合は自動的に処理されます。SDKはthought signatureを含む会話履歴全体を内部で管理します。手動で構築した会話履歴でmodel.generate_content()を直接使用する場合は、署名管理はご自身の責任となります。
thought signatureをデータベースに保存して後で使用できますか?
はい、できます。また、アプリケーションがセッション間で会話を再開する必要がある場合はそうすべきです。各ターンのthought signatureを含む完全なモデルレスポンスを保存してください。再開時には、保存されたすべての署名を含めて会話履歴を再構築します。署名が保存されていないターン(レガシーデータ)がある場合は、ダミー署名"context_engineering_is_the_way_to_go"をプレースホルダーとして使用してください。
thought_signatureフィールドは課金されますか?トークン使用量にカウントされますか?
署名を生成する思考トークンは、thinkingBudgetの設定に関係なく常に課金されます(ai.google.dev、2026年3月)。ただし、署名文字列自体はコンパクトな暗号化表現であり、返送時にリクエストサイズを大幅に増加させることはありません。課金への影響は初期の思考計算にあり、署名の送信にはありません。
なぜエラーメッセージが「missing thought signature」ではなく「invalid thought signature」と表示されるのですか?
エラーメッセージUnable to submit request because it has an invalid thought signature for content at index Nは両方のケースをカバーしています。署名が欠落している場合(フィールド自体が存在しない)と、署名が破損している場合(フィールドは存在するが不正なデータを含む)です。「at index N」は会話履歴のどのターンに問題があるかを示しています。そのインデックスのモデルレスポンスに元のthought signatureが含まれていることを確認してください。
