---
title: 修正綁定到不同對話的思考區塊
url: https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation
description: 在出現表示思考區塊綁定到不同對話的 400 錯誤後，讓對話重新進行，找出您的程式碼變更了什麼，並測試該變更已不復存在。
featureMetadata:
  status: stable
  supportedModels:
    - claude-fable-5-2
    - claude-mythos-5-2
    - claude-fable-5-1
    - claude-mythos-5-1
    - claude-opus-5-5
    - claude-sonnet-5-5
    - claude-haiku-5-5
  supportedPlatforms:
    Claude API: stable
    Amazon Bedrock: stable
    Amazon Bedrock (bedrock-runtime): stable
    Claude Platform on AWS: stable
    Claude Models on Google Cloud (Anthropic managed): stable
    Claude Models on Google Cloud (Google managed): stable
    Microsoft Foundry: stable
---

再次傳送相同的請求不會成功，因為您的歷史記錄仍包含您的程式碼所做的變更。傳送 `"drop_block"` 以[立即停止錯誤](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error)。長期修正是讓您的程式碼成為[「append-only」（僅附加）](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#prefix-check)。

## 錯誤：The block is bound to a different conversation

該思考區塊未通過[「prefix check」（前綴檢查）](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#prefix-check)：在 Claude 產生它之後，它之前的某些內容發生了變更（請參閱[什麼算是變更](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#what-counts-as-an-edit)），或者位於其他思考區塊之間的某個思考區塊被省略或移動了。錯誤看起來如下，並且可能接著[指出變更了什麼](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error-details)：

```text wrap
messages.1.content.0: Invalid `signature` in `thinking` block. The block is bound to a different conversation. Remove the block, or set `thinking.block_binding.prefix_mismatch_behavior` to "drop_block".
```

「A different conversation」（不同的對話）指的是區塊之前的內容不同：[前綴檢查](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#prefix-check)不會比較工作階段或使用者。錯誤訊息要求您移除該區塊，但[只移除該區塊是不夠的](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#remove-by-hand)。[其他錯誤](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#similar-errors)可能看起來很類似。

如果該應用程式不是您的，請開始新的對話並告知其維護者。如果您[移除了機密、個人資料或注入的文字](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions#remove-sensitive-content)，或者您的請求[關閉思考](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#turning-thinking-off)，請[手動移除思考](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#remove-by-hand)，而不是執行步驟 1。

<Steps>
  <Step title="立即停止錯誤">
    將 `thinking.block_binding.prefix_mismatch_behavior` 設為 `"drop_block"`，並傳送 [beta 標頭](https://platform.claude.com/docs/zh-TW/api/beta-headers#beta-features-on-other-platforms) `anthropic-beta: thinking-binding-controls-2026-08-01`。請在該對話之後的每個請求中都這樣做，因為 API 不會在請求之間儲存此設定。即使您修正了程式碼，已儲存的對話仍包含該變更，因此請將此設定與對話一起儲存。如下所示，將 `type` 設為 `"adaptive"`：

    ```json
    {
      "thinking": {
        "type": "adaptive",
        "block_binding": {
          "prefix_mismatch_behavior": "drop_block"
        }
      }
    }
    ```

    在 SDK 中，請呼叫 beta Messages 方法並傳入標頭值，如同[測試程式](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#how-to-tell-whether-your-integration-is-impacted-details)的做法。如果錯誤[仍要求該標頭](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#setting-not-received)，表示標頭沒有送達。

    這會透過捨棄無效的思考來停止錯誤，但[可能花費更多](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost)，也可能影響輸出品質與「latency」（延遲）。下一個請求會成功，且其 `input_transformations` 陣列會列出 API 捨棄的每個區塊。

    如果您的請求未設定 `thinking` 參數，加入它不會改變其他任何事情，因為[具備「preserved thinking」（保留思考）的模型](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#outcomes)預設會以自適應方式思考。
  </Step>

  <Step title="長期修正">
    讓您的整合成為僅附加：

    1. 找出變更。錯誤可能會指出它。若要找出您的程式碼在哪裡做出變更，請執行 `claude update`，然後在您程式碼的儲存庫中，於 Claude Code 中執行 `/claude-api preserved-thinking-migration`。或者[手動尋找](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change-details)。
    2. 停止做出該變更，否則新的對話也可能出現此錯誤。[改為在結尾傳送更新](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions)。
    3. 持續為每個進行中的對話傳送[其最後一次成功請求](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions#saved-sessions)的 `system` 和 `tools`。
  </Step>
</Steps>

如果變更是最近發生的，您也可以改為復原它：將您的程式碼所變更的內容還原。變更之前的思考會再次有效。此後產生的思考則會未通過前綴檢查，因此請移除它，或持續傳送 `"drop_block"`。

## 捨棄思考的代價

Claude 可能會花費更多輸出 token 來重新推導它已無法讀取的推理。捨棄這些區塊也會使從第一個被捨棄的區塊開始的「prompt cache」（提示快取）失效。

當每一輪都有內容變更時，每一輪都會失去先前各輪的思考，因此增加的成本會反覆出現。在依賴 `"drop_block"` 之前，請在您自己的工作負載上執行評估。

<Frame>
  ![變更後的四個請求：第一個被拒絕；接下來三個捨棄舊的思考，並保留每個新區塊](https://platform.claude.com/docs/zh-TW/images/preserved-thinking-drop-block-loss.svg)
</Frame>

使用 `"drop_block"` 讓仍包含您正在修正之變更的既有對話繼續進行，以及用於計畫中的捨棄，例如[在您自己的摘要之後](https://platform.claude.com/docs/zh-TW/build-with-claude/compaction-thinking-blocks#own-summary)。不要一直開著它來掩蓋您的程式碼持續做出的變更。一旦無效區塊已從歷史記錄中移除，您就可以[停止傳送它](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#drop-block-cost-details)。

## 找出您的程式碼變更了什麼

變更位於 API 指出的第一個區塊之前。400 錯誤可能會說明變更了什麼，例如 `system`、`tools`、缺少的思考區塊，或第一則不同的訊息。如果沒有錯誤，或錯誤沒有說明，請[從您手上有的資訊著手](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change-details)，例如 `prefix_binding_mismatch` 條目或增加的輸出 token。

## 測試您的程式碼是否有未通過前綴檢查的情況

在您看過測試失敗之後，才能信任它。首先，透過您自己的程式碼執行一個會讓 Claude 思考的工作階段，並刻意變更某些內容。在這個步驟中傳送 `"drop_block"`，讓回應列出每個無效區塊，而不是在第一個就停止，如[五個步驟和一個程式](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#how-to-tell-whether-your-integration-is-impacted-details)所示。

接著移除該變更，並執行您真實的工作階段。在每個請求中傳送 beta 標頭 `thinking-binding-controls-2026-08-01`，並將 [`prefix_mismatch_behavior`](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#preserved-thinking-controls) 設為 `"error"`，如此一來，您的程式碼在這些工作階段中做出的變更會以 400 錯誤使建置失敗。

請測試會進行壓縮、較晚加入工具、變更指示、[切換模型](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#switching-models)或恢復的工作階段：一般的輪次不會執行到那些程式碼。

乾淨的執行沒有 `prefix_binding_mismatch` 條目，也沒有錯誤。它只顯示在您執行的工作階段中，它所檢查的區塊是有效的。在以下情況下，它無法證明任何事：

* 該工作階段沒有思考區塊
* 您的程式碼移除了所有思考，或該模型不具備保留思考
* 您沒有傳送 beta 標頭，而[模型可能會讓未通過前綴檢查的區塊通過](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#outcomes)且不產生錯誤

## 監看正式環境，並找出在沒有錯誤的情況下遺失的推理

記錄每個 400 錯誤，並[在程式碼中處理它](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#handle-the-error-in-code)，讓對話得以繼續。如果您改為不設定 `prefix_mismatch_behavior`，請[監看正式環境流量](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#watch-production-traffic)，留意送達 Claude 的未通過前綴檢查的思考。

推理可能會在沒有錯誤的情況下遺失，原因包括 `"drop_block"`、批次項目、切換模型、移至[另一個帳戶](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#account-bound-thinking)，或不回傳任何思考的程式碼。使用 beta 標頭時，除了最後一項之外，每一項都會留下條目。對於最後一項，請檢查您的請求是否包含 `thinking` 區塊。

## 技術細節

### 錯誤訊息還可能說明什麼

在 API 能夠判斷的情況下，錯誤訊息會接著指出變更了什麼，例如 `system`、`tools`、第一則不同的訊息或區塊、缺少或新增的內容，或是缺少或順序錯亂的較早思考區塊。該句子的措辭可能會改變，因此請勿以它進行比對。如果請求沒有 beta 標頭，錯誤訊息會加上這句話：

```text wrap
That setting requires the `thinking-binding-controls-2026-08-01` value in the `anthropic-beta` header.
```

### 錯誤仍要求該標頭，或顯示 `Extra inputs are not permitted`

如果錯誤仍要求該標頭，表示標頭沒有送達 API：代理伺服器或程式庫可能已將其移除。另一個以 `block_binding: Extra inputs are not permitted` 結尾的錯誤，代表相同的情況，或代表思考已關閉。

### 手動移除無效的思考

在您無法傳送此設定的情況下，或在下列其中一種情況下，請使用此方法：

* 在您移除機密、個人資料或注入的文字之後，因為 `"drop_block"` 會將思考留在您儲存的歷史記錄中。
* 當思考已關閉（`"disabled"` 或 `"between_tools"`）時，因為 `"drop_block"` 需要 `"adaptive"`，而這會開啟思考並增加輸出 token。

1. 移除錯誤指出的區塊，以及其後的每個 `thinking` 和 [`redacted_thinking`](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#redacted-thinking-blocks) 區塊，否則相同的錯誤接著會指出下一個無效區塊。但如果您的歷史記錄包含 `role: "system"` 訊息，或連續兩則相同角色的訊息，請移除每個 `thinking` 和 `redacted_thinking` 區塊。錯誤會將這類訊息計為其前一則訊息的一部分，因此它指出的位置可能會小於您陣列中的索引。`input_transformations` 條目的 `path` 則會將每則訊息分開計算。
2. 保留所有其他區塊，然後再次傳送請求。不要把已移除的區塊放回去。

### 與此錯誤相似的錯誤

這些錯誤不會說明區塊綁定到不同的對話，而設定 `prefix_mismatch_behavior` 可能無法消除它們：

* 在「Invalid `signature` in `thinking` block」之後就結束、包含「cannot be modified」，或與 `budget_tokens` 有關的訊息：[思考功能疑難排解](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-troubleshooting)
* 與 `temperature` 或預先填入的回覆有關的訊息：[限制與功能相容性](https://platform.claude.com/docs/zh-TW/build-with-claude/thinking#limits-and-feature-compatibility)

### 何時可以停止傳送 `"drop_block"`

若要停止傳送 `"drop_block"`，請移除它所捨棄的區塊，並保留此後產生的思考。如果沒有其他任何變更，該對話接著就能在使用 `"error"` 時通過。

### 在程式碼中處理錯誤

若要在程式碼中處理錯誤，請在每個請求中傳送 beta 標頭和 `"error"`，讓失敗在每個模型上都以 400 錯誤呈現。收到錯誤時，只將該對話切換為在之後的每個請求中使用 `"drop_block"`，將此選擇與該對話一起儲存，再傳送一次，並記錄該錯誤。如果相同的錯誤再次出現，表示此設定沒有送達 API：請參閱[錯誤仍要求該標頭，或顯示 `Extra inputs are not permitted`](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#setting-not-received)。

您的程式碼必須透過 `message` 欄位來辨識此錯誤，這是「不要比對錯誤文字」這項一般建議的例外。每個 400 錯誤的類型都是 `invalid_request_error`，而此錯誤沒有 `error.details.error_code`。請只比對「The block is bound to a different conversation」，因為訊息的其餘部分可能會改變。

### 您沒有收到錯誤，或錯誤沒有說明變更了什麼

* **400 錯誤，且未指出任何變更：** 請自行比較請求。其中一個原因是傳送了壓縮區塊，卻沒有移除它所摘要的訊息。

* **`prefix_binding_mismatch` 條目：** 將直到第一個條目 `path` 為止的 `system`、`tools` 和 `messages`，與產生該區塊時的對話進行比較。如果每個區塊都被列出，請從 `system` 和 `tools` 開始。

  如果沒有任何差異，請尋找[內容已變更的圖片或文件 URL](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions#files-by-id)、MCP 伺服器變更過的工具清單（請參閱[固定 MCP 伺服器的工具清單](https://platform.claude.com/docs/zh-TW/agents-and-tools/mcp-connector#pin-mcp-tool-list)），或被省略、移動或放回的思考區塊。如果沒有請求記錄，請使用 `"error"` 再次傳送請求，並閱讀說明差異之處的句子（如果有的話）。

* **中間有不屬於您的代理伺服器或程式庫：** 比較它傳送的內容與您傳送的內容，並讓其維護者參閱[程式庫、代理伺服器和閘道](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions#libraries-proxies-gateways)。

* **只是懷疑，且沒有 Claude Code：** 擷取某個對話的請求主體，選擇包含壓縮或工具變更的對話。將每個請求主體與前一個進行比較，排除其新的輪次。

### 可能失敗的測試的五個步驟，以及執行這些步驟的程式

1. 在您自己的程式碼中，對[具備保留思考的模型](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#outcomes)傳送工作階段的每個請求時，都附上 beta 標頭和 `"drop_block"`。
2. 使用會讓 Claude 思考的提示，並檢查第一個回應是否有 `thinking` 區塊。使用自適應思考時，Claude 可能會在簡單的提示上略過思考。
3. 只在原因為 `prefix_binding_mismatch` 的 `input_transformations` 條目上判定失敗。要求空陣列的測試在切換模型後也會失敗，因為屆時預期會出現 `model_binding_mismatch` 或 `organization_binding_mismatch` 的條目。
4. 刻意變更某些內容，例如只在第三個請求中加入 `system` 提示。
5. 檢查 `input_transformations` 是否列出位於變更之後的思考區塊。如果沒有列出任何區塊，請檢查歷史記錄是否包含思考區塊。

此程式執行步驟 1、2、4 和 5。它會印出每個回應有多少個思考區塊和 `input_transformations` 條目，然後印出每個條目，也就是步驟 3 要檢查的內容：

<CodeGroup exclude="shell:cURL, shell:CLI">
  <CodeGroupItem language="cURL">
    此工作流程需要的邏輯超出單一 shell 命令所能處理的範圍。請使用 [Anthropic SDK](https://platform.claude.com/docs/zh-TW/cli-sdks-libraries/overview) 來執行它。
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    此工作流程需要的邏輯超出單一 shell 命令所能處理的範圍。請使用 [Anthropic SDK](https://platform.claude.com/docs/zh-TW/cli-sdks-libraries/overview) 來執行它。
  </CodeGroupItem>

  ```python Python
  client = anthropic.Anthropic()

  user_turns = [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many have exactly 8?",
      "How many have exactly 10?",
  ]

  messages = []
  for turn, user_turn in enumerate(user_turns, start=1):
      messages.append({"role": "user", "content": user_turn})
      response = client.beta.messages.create(
          model="claude-opus-5-5",
          max_tokens=16000,
          thinking={
              "type": "adaptive",
              "block_binding": {"prefix_mismatch_behavior": "drop_block"},
          },
          # 只有最後一個請求加入了系統提示，刻意變更前綴
          system="Answer briefly." if turn == len(user_turns) else anthropic.omit,
          messages=messages,
          betas=["thinking-binding-controls-2026-08-01"],
      )
      messages.append({"role": "assistant", "content": response.content})
      thinking_blocks = sum(block.type == "thinking" for block in response.content)
      entries = response.input_transformations or []
      print(f"thinking blocks: {thinking_blocks}, entries: {len(entries)}")
      for entry in entries:
          if entry.type == "thinking_dropped":
              print(entry.type, entry.path, entry.reason)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const userTurns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many have exactly 8?",
    "How many have exactly 10?"
  ];

  const messages: Anthropic.Beta.BetaMessageParam[] = [];
  for (const [turnIndex, userTurn] of userTurns.entries()) {
    messages.push({ role: "user", content: userTurn });
    const response = await client.beta.messages.create({
      model: "claude-opus-5-5",
      max_tokens: 16000,
      thinking: {
        type: "adaptive",
        block_binding: { prefix_mismatch_behavior: "drop_block" }
      },
      // 只有最後一個請求加入系統提示，刻意變更前綴
      system: turnIndex === userTurns.length - 1 ? "Answer briefly." : undefined,
      messages,
      betas: ["thinking-binding-controls-2026-08-01"]
    });
    messages.push({ role: "assistant", content: response.content });
    const thinkingBlocks = response.content.filter((block) => block.type === "thinking");
    const entries = response.input_transformations ?? [];
    console.log(`thinking blocks: ${thinkingBlocks.length}, entries: ${entries.length}`);
    for (const entry of entries) {
      if (entry.type === "thinking_dropped") {
        console.log(entry.type, entry.path, entry.reason);
      }
    }
  }
  ```

  ```csharp C#
  using Anthropic.Models.Beta;
  using Anthropic.Models.Beta.Messages;
  using Model = Anthropic.Models.Messages.Model;

  AnthropicClient client = new();

  string[] userTurns =
  [
      "How many positive integers below 500 have exactly 6 positive divisors?",
      "How many have exactly 8?",
      "How many have exactly 10?",
  ];

  List<BetaMessageParam> messages = [];
  foreach (var (turnIndex, userTurn) in userTurns.Index())
  {
      messages.Add(new BetaUserMessageParam { Content = userTurn });
      var response = await client.Beta.Messages.Create(
          new()
          {
              Model = Model.ClaudeOpus5_5,
              MaxTokens = 16000,
              Thinking = new BetaThinkingConfigAdaptive
              {
                  BlockBinding = new()
                  {
                      PrefixMismatchBehavior = BetaThinkingPrefixMismatchBehavior.DropBlock,
                  },
              },
              // 只有最後一個請求加入系統提示，刻意改變前綴
              System = turnIndex == userTurns.Length - 1 ? new("Answer briefly.") : null,
              Messages = messages,
              Betas = [AnthropicBeta.ThinkingBindingControls2026_08_01],
          }
      );
      messages.Add(new BetaAssistantMessageParam
      {
          Content = response.Content.Select(block => new BetaContentBlockParam(block.Json)).ToList(),
      });
      var thinkingBlocks = response.Content.Count(block => block.TryPickThinking(out _));
      var entries = response.InputTransformations ?? [];
      Console.WriteLine($"thinking blocks: {thinkingBlocks}, entries: {entries.Count}");
      foreach (var entry in entries)
      {
          if (entry.TryPickThinkingDropped(out var dropped))
          {
              Console.WriteLine($"{dropped.Type} {dropped.Path} {dropped.Reason.Raw()}");
          }
      }
  }
  ```

  ```go Go
  client := anthropic.NewClient()

  userTurns := []string{
  	"How many positive integers below 500 have exactly 6 positive divisors?",
  	"How many have exactly 8?",
  	"How many have exactly 10?",
  }

  messages := []anthropic.BetaMessageParam{}
  for turnIndex, userTurn := range userTurns {
  	messages = append(messages, anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock(userTurn)))
  	// 只有最後一個請求加入了系統提示，刻意改變前綴
  	var system []anthropic.BetaTextBlockParam
  	if turnIndex == len(userTurns)-1 {
  		system = []anthropic.BetaTextBlockParam{{Text: "Answer briefly."}}
  	}
  	response, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
  		Model:     anthropic.ModelClaudeOpus5_5,
  		MaxTokens: 16000,
  		Thinking: anthropic.BetaThinkingConfigParamUnion{
  			OfAdaptive: &anthropic.BetaThinkingConfigAdaptiveParam{
  				BlockBinding: anthropic.BetaThinkingBlockBindingParam{
  					PrefixMismatchBehavior: anthropic.BetaThinkingPrefixMismatchBehaviorDropBlock,
  				},
  			},
  		},
  		System:   system,
  		Messages: messages,
  		Betas:    []anthropic.AnthropicBeta{anthropic.AnthropicBetaThinkingBindingControls2026_08_01},
  	})
  	if err != nil {
  		log.Fatal(err)
  	}
  	messages = append(messages, response.ToParam())
  	thinkingBlocks := 0
  	for _, block := range response.Content {
  		if block.Type == "thinking" {
  			thinkingBlocks++
  		}
  	}
  	fmt.Printf("thinking blocks: %d, entries: %d\n", thinkingBlocks, len(response.InputTransformations))
  	for _, entry := range response.InputTransformations {
  		if entry.Type == "thinking_dropped" {
  			fmt.Println(entry.Type, entry.Path, entry.Reason)
  		}
  	}
  }
  ```

  ```java Java
  import com.anthropic.models.beta.AnthropicBeta;
  import com.anthropic.models.beta.messages.BetaContentBlock;
  import com.anthropic.models.beta.messages.BetaInputTransformation;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaThinkingBlockBinding;
  import com.anthropic.models.beta.messages.BetaThinkingConfigAdaptive;
  import com.anthropic.models.beta.messages.BetaThinkingPrefixMismatchBehavior;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

  void main() {
      AnthropicClient client = AnthropicOkHttpClient.fromEnv();

      List<String> userTurns = List.of(
          "How many positive integers below 500 have exactly 6 positive divisors?",
          "How many have exactly 8?",
          "How many have exactly 10?");

      MessageCreateParams.Builder conversation = MessageCreateParams.builder()
          .model(Model.CLAUDE_OPUS_5_5)
          .maxTokens(16000L)
          .thinking(BetaThinkingConfigAdaptive.builder()
              .blockBinding(BetaThinkingBlockBinding.builder()
                  .prefixMismatchBehavior(BetaThinkingPrefixMismatchBehavior.DROP_BLOCK)
                  .build())
              .build())
          .addBeta(AnthropicBeta.THINKING_BINDING_CONTROLS_2026_08_01);

      for (int turnIndex = 0; turnIndex < userTurns.size(); turnIndex++) {
          if (turnIndex == userTurns.size() - 1) {
              // 只有最後一個請求加入了系統提示，刻意改變了前綴
              conversation.system("Answer briefly.");
          }
          conversation.addUserMessage(userTurns.get(turnIndex));
          BetaMessage response = client.beta().messages().create(conversation.build());
          conversation.addMessage(response);
          long thinkingBlocks = response.content().stream()
              .filter(BetaContentBlock::isThinking)
              .count();
          List<BetaInputTransformation> entries = response.inputTransformations().orElse(List.of());
          IO.println("thinking blocks: " + thinkingBlocks + ", entries: " + entries.size());
          for (BetaInputTransformation entry : entries) {
              entry.thinkingDropped().ifPresent(dropped ->
                  IO.println(entry.type() + " " + dropped.path() + " " + dropped.reason()));
          }
      }
  }
  ```

  ```php PHP
  use Anthropic\Beta\AnthropicBeta;
  use Anthropic\Beta\Messages\BetaThinkingBlock;
  use Anthropic\Beta\Messages\BetaThinkingBlockBinding;
  use Anthropic\Beta\Messages\BetaThinkingConfigAdaptive;
  use Anthropic\Beta\Messages\BetaThinkingDroppedInputTransformation;
  use Anthropic\Beta\Messages\BetaThinkingPrefixMismatchBehavior;
  use Anthropic\Client;
  use Anthropic\Messages\Model;

  $client = new Client();

  $userTurns = [
      'How many positive integers below 500 have exactly 6 positive divisors?',
      'How many have exactly 8?',
      'How many have exactly 10?',
  ];

  $messages = [];
  foreach ($userTurns as $turnIndex => $userTurn) {
      $messages[] = ['role' => 'user', 'content' => $userTurn];
      $response = $client->beta->messages->create(
          model: Model::CLAUDE_OPUS_5_5,
          maxTokens: 16000,
          thinking: BetaThinkingConfigAdaptive::with(
              blockBinding: BetaThinkingBlockBinding::with(
                  prefixMismatchBehavior: BetaThinkingPrefixMismatchBehavior::DROP_BLOCK,
              ),
          ),
          // 只有最後一個請求加入了系統提示，藉此刻意改變前綴
          system: $turnIndex === array_key_last($userTurns) ? 'Answer briefly.' : null,
          messages: $messages,
          betas: [AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
      );
      $messages[] = ['role' => 'assistant', 'content' => $response->content];
      $thinkingBlocks = array_filter(
          $response->content,
          fn ($block) => $block instanceof BetaThinkingBlock,
      );
      $entries = $response->inputTransformations ?? [];
      echo 'thinking blocks: ', count($thinkingBlocks), ', entries: ', count($entries), PHP_EOL;
      foreach ($entries as $entry) {
          if ($entry instanceof BetaThinkingDroppedInputTransformation) {
              echo $entry->type, ' ', $entry->path, ' ', $entry->reason, PHP_EOL;
          }
      }
  }
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  user_turns = [
    "How many positive integers below 500 have exactly 6 positive divisors?",
    "How many have exactly 8?",
    "How many have exactly 10?"
  ]

  messages = []
  user_turns.each_with_index do |user_turn, turn_index|
    messages << { role: "user", content: user_turn }
    # 只有最後一個請求加入系統提示，刻意變更前綴
    system_param = (turn_index == user_turns.length - 1) ? { system_: "Answer briefly." } : {}
    response = client.beta.messages.create(
      model: Anthropic::Model::CLAUDE_OPUS_5_5,
      max_tokens: 16_000,
      thinking: {
        type: "adaptive",
        block_binding: { prefix_mismatch_behavior: "drop_block" }
      },
      messages: messages,
      betas: [Anthropic::AnthropicBeta::THINKING_BINDING_CONTROLS_2026_08_01],
      **system_param
    )
    messages << { role: "assistant", content: response.content }
    thinking_blocks = response.content.count { |block| block.is_a?(Anthropic::Beta::BetaThinkingBlock) }
    entries = response.input_transformations || []
    puts "thinking blocks: #{thinking_blocks}, entries: #{entries.length}"
    entries.each do |entry|
      if entry.is_a?(Anthropic::Beta::BetaThinkingDroppedInputTransformation)
        puts "#{entry.type} #{entry.path} #{entry.reason}"
      end
    end
  end
  ```
</CodeGroup>

```text Output wrap
thinking blocks: 1, entries: 0
thinking blocks: 1, entries: 0
thinking blocks: 1, entries: 2
thinking_dropped messages.1.content.0 prefix_binding_mismatch
thinking_dropped messages.3.content.0 prefix_binding_mismatch
```

如果以 `"error"` 取代 `"drop_block"`，第三個請求會收到 [400 錯誤](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#prefix-mismatch-error)。

### 每個 `input_transformations` 條目的含義，以及哪些需要由您修正

使用 beta 標頭時，來自支援思考之模型的回應會在 `usage` 旁邊包含 `input_transformations` 陣列。當沒有任何內容被捨棄、也沒有任何無效內容被放行時，它是空的。當您使用「streaming」（串流）時，它位於 `message_start` 事件的 `message` 中；在串流中途發生備援切換後，以最後的 `message_delta` 事件所攜帶的陣列為準。與錯誤中的位置不同，`path` 一律是該區塊在您傳送時的位置：

```json
{
  "input_transformations": [
    {
      "type": "thinking_dropped",
      "path": "messages.1.content.0",
      "reason": "prefix_binding_mismatch"
    }
  ]
}
```

每個條目的 `type` 和 `reason`，以及它們的含義：

* **`thinking_dropped`、`prefix_binding_mismatch`：** 此區塊之前的內容與它所記錄的不同。需要由您修正：[找出您的程式碼變更了什麼](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/fix-bound-to-a-different-conversation#find-the-change)。
* **`thinking_mismatch_allowed`、`prefix_binding_mismatch`：** 情況相同，但 Claude 讀取了未經變更的區塊，且該區塊會被計費。此條目只會在請求未包含此設定時，於[部分模型](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#outcomes)上出現。需要由您修正。
* **`thinking_dropped`、`model_binding_mismatch`：** 此模型無法讀取來自產生該區塊之模型的區塊。不需要由您修正：[持續傳送整個對話](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#switching-models)。
* **`thinking_dropped`、`organization_binding_mismatch`：** 該區塊由另一個帳戶產生，因此[API 捨棄了它](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking#account-bound-thinking)。不需要由您修正。

請忽略您無法辨識其 `type` 或 `reason` 的條目。

### 批次與 token 計數

* **[訊息批次](https://platform.claude.com/docs/zh-TW/build-with-claude/batch-processing)：** 不設定 `prefix_mismatch_behavior` 的項目永遠不會收到 400 錯誤。API 會捨棄無效的區塊，或者在[部分模型](https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/prefix-checks#outcomes)上，可能會讓它們通過。設定 `"error"` 的項目在某個區塊未通過前綴檢查時，會以 `errored` 結果結束。`block_binding` 放在該項目的 `params.thinking` 中。
* **[Token 計數](https://platform.claude.com/docs/zh-TW/build-with-claude/token-counting)：** 在 Claude API 上，token 計數可能會傳回相同的 400 錯誤，並在相同標頭下接受 `prefix_mismatch_behavior`。它不會將被捨棄的區塊計入，也不會傳回 `input_transformations`。

## 後續步驟

<CardGroup cols={2}>
  <Card title="變更工具或指示而不使前綴檢查失敗" icon="edit" href="https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking/change-tools-or-instructions">
    針對您的程式碼對對話所做的每種變更，應改為傳送什麼。
  </Card>

  <Card title="保留思考" icon="book" href="https://platform.claude.com/docs/zh-TW/build-with-claude/preserved-thinking">
    什麼是保留思考、思考區塊與什麼綁定，以及切換模型或帳戶。
  </Card>

  <Card title="思考功能疑難排解" icon="wrench" href="https://platform.claude.com/docs/zh-TW/build-with-claude/thinking-troubleshooting">
    其他思考錯誤的修正方式，例如無法驗證的簽章。
  </Card>
</CardGroup>
