Vertex/Bedrock: `thinking.display:"summarized"` stripped from request body → empty thinking on Opus 4.8/4.7 (regression 2.1.150→2.1.177, still in 2.1.193)

Resolved 💬 3 comments Opened Jun 26, 2026 by maxim092001 Closed Jun 30, 2026

Summary

On the Vertex (and Bedrock) provider path, Claude Code strips thinking.display from the request body, so the server applies the Opus 4.8 / 4.7 default display:"omitted" and returns thinking blocks with a signature but empty thinking texteven when the user explicitly passes --thinking adaptive --thinking-display summarized.

This is a regression: it works on 2.1.150, and is broken from 2.1.177 through 2.1.193 (latest). The direct Anthropic API path is unaffected — the same CLI version returns non-empty summarized thinking on first-party. The discriminator is purely the provider.

This is likely the underlying root cause behind #56356 ("even passing --thinking adaptive --thinking-display summarized does not fix it") for Vertex/Bedrock users, and is distinct from the first-party "harness doesn't request display" angle in #63358 / #49268.

Environment

  • CLI: @anthropic-ai/claude-code 2.1.193 (GIT_SHA a1938d2a, build 2026-06-25), native binary; also reproduced on 2.1.177 (GIT_SHA 6fae7a0).
  • Last working version: 2.1.150 (GIT_SHA 28d4819).
  • Provider: Vertex (CLAUDE_CODE_USE_VERTEX=1, CLOUD_ML_REGION=global).
  • Model: claude-opus-4-8[1m]. Thinking: --thinking adaptive --thinking-display summarized, --effort high.

Minimal repro

unset ANTHROPIC_API_KEY
export CLAUDE_CODE_USE_VERTEX=1 CLOUD_ML_REGION=global ANTHROPIC_VERTEX_PROJECT_ID=<your-project>
export MAX_THINKING_TOKENS=6000   # only to make adaptive reliably emit a thinking block for the test
claude -p --output-format stream-json --verbose --include-partial-messages \
  --model "claude-opus-4-8[1m]" --thinking-display summarized \
  "Reason step by step, then answer: a bat and ball cost \$1.10; the bat is \$1.00 more than the ball. How much is the ball?"

Expected: a thinking content block with non-empty summarized text (plus signature).
Actual: a thinking block with signature present but thinking == "" and zero thinking_delta events.

Evidence

1. The display field is dropped from the Vertex request body

Captured the exact outgoing request (via CLAUDE_CODE_SKIP_VERTEX_AUTH=1 + a local ANTHROPIC_VERTEX_BASE_URL), same flags in all cases:

| Binary / provider | thinking on the wire | Result |
|---|---|---|
| 2.1.177 Vertex | {"type":"adaptive"}display missing | empty thinking |
| 2.1.193 Vertex | {"type":"adaptive"}display missing | empty thinking |
| 2.1.150 Vertex | {"type":"enabled","budget_tokens":31999,"display":"summarized"} | works |
| 2.1.177 Anthropic (first-party) | {"type":"adaptive","display":"summarized"} | works |

2. Live Vertex confirmation (2.1.193, Opus 4.8)

| 2.1.193 Vertex | thinking block | signature | thinking text | thinking_delta |
|---|---|---|---|---|
| default | present | 396 chars | 0 (empty) | 0 |
| + CLAUDE_CODE_EXTRA_BODY='{"thinking":{"type":"adaptive","display":"summarized"}}' | present | 540 chars | 224 chars ✅ | 22 |

Root cause

The per-request body builder gates the thinking.display value behind a first-party-only provider allow-list that omits vertex/bedrock.

2.1.150 (working) — no provider gate:

oH = (thinkingEnabled) ? q.display : void 0          // display always forwarded
// -> {type:"adaptive", display:oH} / {type:"enabled", budget_tokens, display:oH}

2.1.177 / 2.1.193 (broken) — new gate:

// 2.1.193 symbol names shown:
Vr = Un && YO() && FOt(u) ? n.display : void 0        // Un = thinking enabled
function YO(){ return w4r() && !b$e() }
function w4r(){ let e = yr(); return e==="firstParty" || e==="anthropicAws" || e==="foundry" }  // omits "vertex"/"bedrock"
function b$e(){ return at(process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS) || C8("hipaa") }
function yr(){ ... process.env.CLAUDE_CODE_USE_VERTEX ? "vertex" : "firstParty" }
// -> {type:"adaptive", display: Vr}  with Vr === undefined on Vertex -> serializes to {"type":"adaptive"}

With CLAUDE_CODE_USE_VERTEX, yr()==="vertex", which is not in w4r()'s allow-list ⇒ YO() is false ⇒ Vr becomes undefineddisplay is omitted from the body ⇒ server defaults to display:"omitted". (In 2.1.177 the identical logic is S9 = r9 && NN() && tW_(A) ? q.display : void 0, Ek8(){return H==="firstParty"||H==="anthropicAws"||H==="foundry"}.)

thinking.display is a provider-agnostic field (it worked on Vertex in 2.1.150 and the underlying API supports it), so folding it behind the first-party "experimental betas" provider gate is incorrect.

Scope / blast radius

  • yr() can return bedrock, vertex, foundry, firstParty, anthropicAws, mantle, gateway. The allow-list w4r() only includes firstParty, anthropicAws, foundryvertex, bedrock, mantle, gateway all lose thinking.display.
  • Because of b$e(), first-party also breaks if CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1 or HIPAA mode is enabled.

Suggested fix

Either (a) add vertex/bedrock (and mantle/gateway) to the w4r()/Ek8() allow-list, or — cleaner — (b) stop gating thinking.display passthrough on YO()/NN() entirely and forward q.display whenever thinking is enabled, restoring the 2.1.150 behavior. thinking.display is not an experimental-beta concern.

Acceptance criteria

  1. Vertex request body contains thinking.display:"summarized" when --thinking-display summarized is set; non-empty summarized thinking is returned for claude-opus-4-8[1m].
  2. --thinking-display omitted still returns signature-only / empty thinking.
  3. Works with and without --include-partial-messages; existing thinking-block signatures remain present.

Workaround (until fixed)

export CLAUDE_CODE_EXTRA_BODY='{"thinking":{"type":"adaptive","display":"summarized"}}'

CLAUDE_CODE_EXTRA_BODY is spread into the body after the CLI's thinking object, re-injecting display on the wire (verified live, see table above). Must use type:"adaptive" — Opus 4.8 rejects type:"enabled" with 400 "thinking.type.enabled" is not supported for this model.

Related

  • #63358 (Opus 4.8 empty thinking — first-party), #49268, #56356 (this is the Vertex/Bedrock root cause for "the flag doesn't fix it").
  • SDK side (downstream impact for claude-agent-sdk users on Vertex): anthropics/claude-agent-sdk-python — filed separately and linked below.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗