From 46d24e7b8c33e26c6d28ab8988a1559e110a870a Mon Sep 17 00:00:00 2001 From: Roo Code Date: Tue, 24 Feb 2026 06:07:04 +0000 Subject: [PATCH] fix: skip fine-grained-tool-streaming beta for older Claude 3 models on Bedrock Older Claude 3 models (Haiku, Opus, Sonnet, and the original 3.5 Sonnet 20240620) do not support the fine-grained-tool-streaming beta flag on AWS Bedrock. Sending this beta causes Bedrock to reject the request with "invalid beta flag". This change adds an exclusion list for these older models and only sends the beta header to Claude models that support it. Closes #11715 --- packages/types/src/providers/bedrock.ts | 10 ++++ src/api/providers/__tests__/bedrock.spec.ts | 63 +++++++++++++++++++++ src/api/providers/bedrock.ts | 12 +++- 3 files changed, 82 insertions(+), 3 deletions(-) diff --git a/packages/types/src/providers/bedrock.ts b/packages/types/src/providers/bedrock.ts index 9ea52bced89..d9571da5bd7 100644 --- a/packages/types/src/providers/bedrock.ts +++ b/packages/types/src/providers/bedrock.ts @@ -520,6 +520,16 @@ export const BEDROCK_REGIONS = [ { value: "us-gov-west-1", label: "us-gov-west-1" }, ].sort((a, b) => a.value.localeCompare(b.value)) +// Older Claude 3 models on Bedrock that do NOT support the fine-grained-tool-streaming beta. +// Sending this beta flag to these models causes Bedrock to reject the request with +// "invalid beta flag". See: https://github.com/RooCodeInc/Roo-Code/issues/11715 +export const BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS = [ + "anthropic.claude-3-haiku-20240307-v1:0", + "anthropic.claude-3-opus-20240229-v1:0", + "anthropic.claude-3-sonnet-20240229-v1:0", + "anthropic.claude-3-5-sonnet-20240620-v1:0", +] as const + export const BEDROCK_1M_CONTEXT_MODEL_IDS = [ "anthropic.claude-sonnet-4-20250514-v1:0", "anthropic.claude-sonnet-4-5-20250929-v1:0", diff --git a/src/api/providers/__tests__/bedrock.spec.ts b/src/api/providers/__tests__/bedrock.spec.ts index 975e38af123..ce53bfb7378 100644 --- a/src/api/providers/__tests__/bedrock.spec.ts +++ b/src/api/providers/__tests__/bedrock.spec.ts @@ -38,6 +38,7 @@ import { AwsBedrockHandler } from "../bedrock" import { ConverseStreamCommand, BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime" import { BEDROCK_1M_CONTEXT_MODEL_IDS, + BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS, BEDROCK_SERVICE_TIER_MODEL_IDS, bedrockModels, ApiProviderError, @@ -843,6 +844,68 @@ describe("AwsBedrockHandler", () => { expect(commandArg.additionalModelRequestFields.anthropic_beta).not.toContain("context-1m-2025-08-07") }) + it("should NOT include fine-grained-tool-streaming beta for older Claude 3 models", async () => { + // Test with Claude 3 Haiku - the model from the original bug report + for (const unsupportedModelId of BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS) { + const handler = new AwsBedrockHandler({ + apiModelId: unsupportedModelId, + awsAccessKey: "test", + awsSecretKey: "test", + awsRegion: "us-east-1", + }) + + const messages: Anthropic.Messages.MessageParam[] = [ + { + role: "user", + content: "Test message", + }, + ] + + mockConverseStreamCommand.mockClear() + + const generator = handler.createMessage("", messages) + await generator.next() + + expect(mockConverseStreamCommand).toHaveBeenCalled() + const commandArg = mockConverseStreamCommand.mock.calls[0][0] as any + + // Older Claude 3 models should NOT have fine-grained-tool-streaming beta + if (commandArg.additionalModelRequestFields?.anthropic_beta) { + expect(commandArg.additionalModelRequestFields.anthropic_beta).not.toContain( + "fine-grained-tool-streaming-2025-05-14", + ) + } + } + }) + + it("should still include fine-grained-tool-streaming beta for newer Claude models", async () => { + const handler = new AwsBedrockHandler({ + apiModelId: "anthropic.claude-3-5-sonnet-20241022-v2:0", + awsAccessKey: "test", + awsSecretKey: "test", + awsRegion: "us-east-1", + }) + + const messages: Anthropic.Messages.MessageParam[] = [ + { + role: "user", + content: "Test message", + }, + ] + + const generator = handler.createMessage("", messages) + await generator.next() + + expect(mockConverseStreamCommand).toHaveBeenCalled() + const commandArg = mockConverseStreamCommand.mock.calls[0][0] as any + + // Newer Claude models should still have the beta + expect(commandArg.additionalModelRequestFields).toBeDefined() + expect(commandArg.additionalModelRequestFields.anthropic_beta).toContain( + "fine-grained-tool-streaming-2025-05-14", + ) + }) + it("should enable 1M context window with cross-region inference for Claude Sonnet 4", () => { const handler = new AwsBedrockHandler({ apiModelId: BEDROCK_1M_CONTEXT_MODEL_IDS[0], diff --git a/src/api/providers/bedrock.ts b/src/api/providers/bedrock.ts index 3ceb2510033..94e0ebb19c4 100644 --- a/src/api/providers/bedrock.ts +++ b/src/api/providers/bedrock.ts @@ -27,6 +27,7 @@ import { BEDROCK_DEFAULT_CONTEXT, AWS_INFERENCE_PROFILE_MAPPING, BEDROCK_1M_CONTEXT_MODEL_IDS, + BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS, BEDROCK_GLOBAL_INFERENCE_MODEL_IDS, BEDROCK_SERVICE_TIER_MODEL_IDS, BEDROCK_SERVICE_TIER_PRICING, @@ -436,9 +437,14 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH anthropicBetas.push("context-1m-2025-08-07") } - // Add fine-grained tool streaming beta for Claude models - // This enables proper tool use streaming for Anthropic models on Bedrock - if (baseModelId.includes("claude")) { + // Add fine-grained tool streaming beta for Claude models that support it. + // Older Claude 3 models (Haiku, Opus, Sonnet, and original 3.5 Sonnet) do not + // support this beta flag and Bedrock rejects the request with "invalid beta flag". + // See: https://github.com/RooCodeInc/Roo-Code/issues/11715 + if ( + baseModelId.includes("claude") && + !BEDROCK_FINE_GRAINED_STREAMING_UNSUPPORTED_IDS.includes(baseModelId as any) + ) { anthropicBetas.push("fine-grained-tool-streaming-2025-05-14") }