Skip to content

bug: Bedrock models that only support adaptive thinking (Opus 4.7+) reject thinking.type: "enabled" requests #280

@blinkagent

Description

@blinkagent

Summary

This is the symmetric counterpart to #219 (fixed by #225).

#225 added adaptive → enabled conversion in augmentRequestForBedrock() for older Bedrock models that don't support adaptive thinking. The reverse conversion is missing: when Claude Code sends thinking.type: "enabled" (its fallback default when it cannot introspect the target model's capabilities) and the resolved Bedrock model is adaptive-only (Opus 4.7+), the body is forwarded unchanged and Bedrock 400s.

With AI Bridge in the path, Claude Code cannot read the application inference profile metadata (the request goes to Coder, not directly to Bedrock), so it falls back to the deprecated enabled shape — which Opus 4.7 rejects per the model card:

Claude Opus 4.7 only supports thinking.type: "adaptive" for extended thinking. Unlike Claude Opus 4.6, thinking.type: "enabled" with budget_tokens is not supported and will return a 400 error.

Error

API Error: 400 {"error":{"message":"POST \"https://bedrock-runtime.us-east-1.amazonaws.com/v1/messages\": 400 Bad Request {\"message\":\"\\\"thinking.type.enabled\\\" is not supported for this model. Use \\\"thinking.type.adaptive\\\" and \\\"output_config.effort\\\" to control thinking behavior.\"}", "type":"api_error"}, ...}

Reproduction

Coder server with:

  • CODER_AIBRIDGE_ENABLED=true
  • CODER_AIBRIDGE_BEDROCK_REGION=us-east-1
  • CODER_AIBRIDGE_BEDROCK_MODEL=us.anthropic.claude-opus-4-7
  • Any valid Bedrock auth

Direct AI Bridge probe with the legacy shape reproduces the 400:

curl -H "x-api-key: $CODER_TOKEN" \
     -H 'Content-Type: application/json' \
     -H 'anthropic-version: 2023-06-01' \
     -X POST https://<coder>/api/v2/aibridge/anthropic/v1/messages \
     -d '{"model":"us.anthropic.claude-opus-4-7","max_tokens":2048,
          "thinking":{"type":"enabled","budget_tokens":1024},
          "messages":[{"role":"user","content":"hi"}]}'
# -> HTTP 400 "thinking.type.enabled" is not supported for this model

The same call against us.anthropic.claude-opus-4-6-v1 succeeds (4.6 still accepts both shapes).

Root cause

In intercept/messages/base.go, augmentRequestForBedrock() already gates on bedrockModelSupportsAdaptiveThinking(model) and calls convertAdaptiveThinkingForBedrock() when the target doesn't support adaptive. There is no symmetric helper for the case where the target only supports adaptive and the incoming request uses enabled.

Proposed fix

In augmentRequestForBedrock(), add the symmetric transformation:

  1. Introduce an "adaptive-only" capability set (Opus 4.7+, presumably future Opus 4.x and Sonnet 4.x as they ship in adaptive-only mode).
  2. If thinking.type == "enabled" and the resolved Bedrock model is in that set, rewrite the body to:
    • thinking: { type: "adaptive" }
    • output_config.effort derived from the original budget_tokens / max_tokens ratio (mirror of the OpenRouter-style mapping used in fix: remove unsupported fields from requests to Bedrock #225, but in reverse: budget < ~25% of max → low, < ~50%medium, otherwise → high).
    • Drop budget_tokens and any related legacy fields the new shape doesn't accept.
  3. Optionally reconsider the Anthropic-Beta: interleaved-thinking-2025-05-14 (and friends) header handling for adaptive-only models, similar to the GovCloud header strip in bug: Anthropic-Beta header forwarded to Bedrock causes invalid beta flag errors #221 / fix: filter unsupported Anthropic-Beta headers from Bedrock #226. Best evidence is that Opus 4.7 still accepts those beta flags, so this may be a no-op — but worth verifying alongside the body rewrite.

The capability set can be hard-coded for now (mirroring the existing string-contains style of bedrockModelSupportsAdaptiveThinking) or driven from the same Bedrock model metadata Claude Code uses when it has direct access.

Workaround

Pin CODER_AIBRIDGE_BEDROCK_MODEL to us.anthropic.claude-opus-4-6-v1. Operationally works but loses 4.7 quality and requires every operator to know to avoid 4.7+ until the underlying fix lands.

Why this matters

  • Without the fix, every customer using AI Bridge → Bedrock with the (commonly recommended) Opus 4.7 model has Claude Code completely broken — every request 400s, in both thinking and non-thinking flows.
  • The error surface is misleading: the 400 looks like a config problem; you have to dig two layers down to realize it's a body-shape mismatch between Claude Code and the Bedrock model.
  • The currently shipped half of the conversion (fix: remove unsupported fields from requests to Bedrock #225) actively encourages the assumption that AI Bridge handles model/shape impedance — so the missing reverse direction is a surprise.

The reporter has offered to test a candidate fix on a staging cluster running v2.32.1.

References


Created on behalf of @stirby

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions