Skip to content

fix(gateway): route Bedrock models without a global profile - #3104

Merged
steebchen merged 1 commit into
mainfrom
bedrock-opus-4-1-invalid-model
Jul 17, 2026
Merged

steebchen merged 1 commit into
mainfrom
bedrock-opus-4-1-invalid-model

Conversation

@steebchen

@steebchen steebchen commented Jul 17, 2026 •

Copy link
Copy Markdown
Member

Problem

The AWS Bedrock dashboard shows claude-opus-4-1-20250805:global failing 100% of the time with:

400 Bad Request
{"message":"The provided model identifier is invalid."}

Root cause

Bedrock's regionConfig uses defaultRegion: "global" + pinDefaultRegion: true, so by default all Bedrock traffic is pinned to the global cross-region inference profile. Most Claude models on Bedrock expose a global CRIS profile — but a handful expose only a us profile and no global one:

  • claude-opus-4-1-20250805
  • llama-3.1-70b-instruct
  • llama-4-scout-17b-instruct
  • llama-4-maverick-17b-instruct

For those, on the default routing path (managed key, no :region suffix):

  1. applyPinnedDefaultRegions dropped the us variant (us !== global), leaving only the region-less synthetic root.
  2. getProviderEndpoint applied the default global. prefix → e.g. global.anthropic.claude-opus-4-1-20250805-v1:0.
  3. Bedrock rejects that id with the reported 400.

Verification (direct Bedrock calls)

Model id Result
us.anthropic.claude-opus-4-1-20250805-v1:0 HTTP 200 ✅
global.anthropic.claude-opus-4-1-20250805-v1:0 HTTP 400 — "The provided model identifier is invalid." ❌
us.meta.llama3-1-70b-instruct-v1:0 HTTP 200 ✅
global.meta.llama3-1-70b-instruct-v1:0 HTTP 400 ❌

Fix

applyPinnedDefaultRegions now detects when a model has regional variants but none matching the provider's default region. In that case the synthetic root cannot be used (it would resolve to the invalid global. prefix), so it pins to the model's concrete regional variants (us) instead. Models that do have a global variant, and Bedrock mappings with no regional variants at all, are unchanged.

The helper was extracted into apps/gateway/src/chat/tools/pin-default-regions.ts with unit tests covering: global-capable models, us-only models (Opus 4.1 + Llama), region-less mappings, explicit :region requests, and provider-key region locks.

This keeps Opus 4.1 (and the Llama models) working on Bedrock via their us profile instead of deactivating them.

Summary by CodeRabbit

  • Bug Fixes

    • Improved regional model selection to avoid invalid or unintended provider-region mappings.
    • Preserved explicit region requests and provider locks during model selection.
    • Correctly prioritizes global profiles or concrete default regions when available.
  • Tests

    • Added coverage for regional mappings, global profiles, explicit region requests, provider locks, and providers without regional variants.

Copilot AI review requested due to automatic review settings July 17, 2026 18:44
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change extracts default-region pinning into a reusable helper, adds concrete regional mapping preference in chat routing, and introduces Vitest coverage for Bedrock region-selection scenarios and pass-through conditions.

Changes

Regional provider selection

Layer / File(s) Summary
Centralize default-region selection
apps/gateway/src/chat/tools/pin-default-regions.ts, apps/gateway/src/chat/chat.ts
applyPinnedDefaultRegions handles requested regions, explicit locks, provider pinning, default regions, and concrete regional mappings; chat imports the helper and prefers explicit regional variants when available.
Validate Bedrock mapping outcomes
apps/gateway/src/chat/tools/pin-default-regions.spec.ts
Tests cover global and concrete-region selection, synthetic-root preservation, and pass-through for requested regions and explicit locks.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main change: fixing Bedrock routing for models that lack a global profile.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bedrock-opus-4-1-invalid-model

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

AWS Bedrock's region routing pins the `global` cross-region inference
profile by default. A handful of Bedrock models expose only a `us` profile
(Claude Opus 4.1, Llama 3.1 70B, Llama 4 Scout/Maverick) and have no `global`
one. For those, applyPinnedDefaultRegions kept only the synthetic root, which
getProviderEndpoint resolves to `global.<externalId>` — an id Bedrock rejects
with 400 "The provided model identifier is invalid.", so every default
request failed.

Verified directly against Bedrock: `global.anthropic.claude-opus-4-1-20250805-v1:0`
and `global.meta.llama3-1-70b-instruct-v1:0` both 400, while the `us.`
prefixed ids return 200.

When a model has regional variants but none matching the provider's default
region, pin to the concrete regional variants instead of the synthetic root.
Extracted applyPinnedDefaultRegions into its own module with unit tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@steebchen
steebchen force-pushed the bedrock-opus-4-1-invalid-model branch from 8d6a2dc to cc51181 Compare July 17, 2026 18:57
@steebchen steebchen changed the title fix(models): deactivate Bedrock Opus 4.1 mapping fix(gateway): route Bedrock models without a global profile Jul 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/gateway/src/chat/tools/pin-default-regions.ts (1)

40-51: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optimize provider lookup and avoid duplicate find operations.

The providers.find lookup is performed twice for every mapping (once in the setup loop and once in the filter loop). While the arrays are likely small, you can improve performance and readability by looking up the provider definition once and caching it.

Additionally, if providers is correctly typed from @llmgateway/models, the explicit as ProviderDefinition | undefined type assertions might be unnecessary.

♻️ Proposed refactor
-		const def = providers.find((p) => p.id === m.providerId) as
-			| ProviderDefinition
-			| undefined;
-		if (m.region === def?.regionConfig?.defaultRegion) {
+		const def = providers.find((p) => p.id === m.providerId);
+		if (def && m.region === def.regionConfig?.defaultRegion) {
 			providerHasDefaultRegion.add(m.providerId);
 		}
 	}
 	return mappings.filter((m) => {
-		const def = providers.find((p) => p.id === m.providerId) as
-			| ProviderDefinition
-			| undefined;
+		const def = providers.find((p) => p.id === m.providerId);
 		if (!def?.regionConfig?.pinDefaultRegion) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/gateway/src/chat/tools/pin-default-regions.ts` around lines 40 - 51,
Refactor the provider lookup in the setup and filtering logic of the
pin-default-regions flow to resolve each mapping’s provider definition once and
reuse the cached result, eliminating both repeated providers.find calls. If the
providers collection is already typed as ProviderDefinition, remove the
redundant ProviderDefinition | undefined assertions while preserving the
existing default-region and pinDefaultRegion behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/gateway/src/chat/tools/pin-default-regions.ts`:
- Around line 40-51: Refactor the provider lookup in the setup and filtering
logic of the pin-default-regions flow to resolve each mapping’s provider
definition once and reuse the cached result, eliminating both repeated
providers.find calls. If the providers collection is already typed as
ProviderDefinition, remove the redundant ProviderDefinition | undefined
assertions while preserving the existing default-region and pinDefaultRegion
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 18a31774-1cc9-4dd2-bde3-a6fb29e62f15

📥 Commits

Reviewing files that changed from the base of the PR and between 8d6a2dc and cc51181.

📒 Files selected for processing (3)
  • apps/gateway/src/chat/chat.ts
  • apps/gateway/src/chat/tools/pin-default-regions.spec.ts
  • apps/gateway/src/chat/tools/pin-default-regions.ts

@steebchen
steebchen added this pull request to the merge queue Jul 17, 2026
Merged via the queue into main with commit 0cdd9d5 Jul 17, 2026
23 of 24 checks passed
@steebchen
steebchen deleted the bedrock-opus-4-1-invalid-model branch July 17, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants