{"record":{"id":"685765d36651428c","repo":"alibaba/open-code-review","slug":"s-cannot-be-q-bedrock-derives-its-host-from-aws","errorCode":null,"errorMessage":"%s cannot be %q: bedrock derives its host from aws_region and signs with the AWS credential chain, so it has no use for a url or a token; configure it as a provider instead (\"provider\": \"bedrock\")","messagePattern":"(.+?) cannot be %q: bedrock derives its host from aws_region and signs with the AWS credential chain, so it has no use for a url or a token; configure it as a provider instead \\(\"provider\": \"bedrock\"\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/llm/resolver.go","lineNumber":242,"sourceCode":"\t}\n\tif sec < 0 {\n\t\treturn 0, fmt.Errorf(\"timeout_sec must be non-negative, got %d\", sec)\n\t}\n\t// Guard against overflow: time.Duration is int64 nanoseconds.\n\tmaxSec := int64(math.MaxInt64 / int64(time.Second))\n\tif int64(sec) > maxSec {\n\t\treturn 0, fmt.Errorf(\"timeout_sec %d overflows time.Duration (max %d)\", sec, maxSec)\n\t}\n\treturn time.Duration(sec) * time.Second, nil\n}\n\n// errBedrockNotConfigurable explains why the two url+token strategies reject the\n// bedrock protocol. Both describe a single HTTP endpoint and carry no place for\n// a region or a profile, and bedrock uses neither the url nor the token they do\n// carry. Accepting the value would switch transports and silently ignore the\n// rest of the block, so it is refused at the point it is read.\nfunc errBedrockNotConfigurable(key string) error {\n\treturn fmt.Errorf(\"%s cannot be %q: bedrock derives its host from aws_region and signs with the AWS credential chain, so it has no use for a url or a token; configure it as a provider instead (\\\"provider\\\": \\\"bedrock\\\")\",\n\t\tkey, ProtocolAnthropicBedrock)\n}\n\n// tryOCREnv reads OCR-specific environment variables.\nfunc tryOCREnv(modelOverride string) (ResolvedEndpoint, bool, error) {\n\turl := os.Getenv(envOCRLLMURL)\n\ttoken := os.Getenv(envOCRLLMToken)\n\tmodel := os.Getenv(envOCRLLMModel)\n\tif modelOverride != \"\" {\n\t\tmodel = modelOverride\n\t}\n\tif url == \"\" || token == \"\" || model == \"\" {\n\t\treturn ResolvedEndpoint{}, false, nil\n\t}\n\n\t// OCR_LLM_PROTOCOL (normalized) wins over OCR_USE_ANTHROPIC when set.\n\tprotocol := \"\"\n\tif raw := strings.TrimSpace(os.Getenv(envOCRLLMProtocol)); raw != \"\" {","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/internal/llm/resolver.go#L224-L260","documentation":"errBedrockNotConfigurable explains why the url+token configuration strategies (OCR_* env vars and the legacy llm config block) reject the bedrock protocol. Bedrock derives its host from aws_region and signs requests with the AWS credential chain, so a single-HTTP-endpoint description carrying only a url and token has no place to express a region or profile, and its url/token fields would be silently ignored. The resolver refuses the value at the point it is read rather than switching transports and dropping the rest of the block.","triggerScenarios":"Setting OCR_LLM_PROTOCOL=anthropic-bedrock while OCR_LLM_URL/OCR_LLM_TOKEN/OCR_LLM_MODEL are set (tryOCREnv), or putting \"protocol\": \"anthropic-bedrock\" inside the legacy url+token llm config block (tryLegacyLlmConfig). Both strategies describe one HTTP endpoint and carry no region/profile field.","commonSituations":"A developer who previously reached Bedrock through an AWS SDK endpoint URL pastes that URL and a token into the OCR env vars; or copies an llm block written for a hosted Anthropic endpoint and flips the protocol to bedrock expecting it to just work.","solutions":["Remove the bedrock protocol value from the url+token strategy (unset OCR_LLM_PROTOCOL or delete the protocol line in the llm block)","Configure bedrock as a provider instead: set \"provider\": \"bedrock\" and add a matching entry under \"providers\" with aws_region (and optionally aws_profile)","Keep OCR_LLM_URL/OCR_LLM_TOKEN only for direct-HTTP protocols such as anthropic or openai"],"exampleFix":"// before\nexport OCR_LLM_URL=https://bedrock-runtime.us-east-1.amazonaws.com\nexport OCR_LLM_TOKEN=aws-token\nexport OCR_LLM_PROTOCOL=anthropic-bedrock\n\n// after — ~/.config/ocr/config.json\n{\n  \"provider\": \"bedrock\",\n  \"model\": \"us.anthropic.claude-sonnet-4-20250514-v1:0\",\n  \"providers\": { \"bedrock\": { \"aws_region\": \"us-east-1\" } }\n}","handlingStrategy":"validation","validationCode":"proto := strings.TrimSpace(os.Getenv(\"OCR_LLM_PROTOCOL\"))\nif proto != \"\" && strings.EqualFold(proto, \"anthropic-bedrock\") {\n    if os.Getenv(\"OCR_LLM_URL\") != \"\" || os.Getenv(\"OCR_LLM_TOKEN\") != \"\" {\n        return errors.New(\"bedrock must be configured as a provider (\\\"provider\\\": \\\"bedrock\\\"), not via url+token env vars\")\n    }\n}","typeGuard":"func isURLTokenProtocol(p string) bool {\n    switch p {\n    case \"anthropic\", \"openai\", \"openai-responses\":\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Never put bedrock under a url+token strategy; reserve OCR_LLM_URL/OCR_LLM_TOKEN for hosted HTTP endpoints","Configure AWS-region backends via \"provider\": \"bedrock\" with aws_region/aws_profile","Keep protocol selection (OCR_LLM_PROTOCOL) away from ambient-auth providers"],"tags":["configuration","bedrock","aws","env-vars"],"backgroundTag":"incompatible-provider-config","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}