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)

Status Closed — duplicate
Reported on v2.1.150
Maintainer reply None cached
Activity 3 comments · opened Jun 26, 2026 · 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 ↗