Skip to content

Python: [Bug]: BedrockEmbeddingClient ignores an explicit region when a boto3_session is passed, and reports the wrong region #9348

Closed

Description

Observed Behavior

BedrockEmbeddingClient picks its region differently from BedrockChatClient, and its region attribute does not match the region it sends requests to:

  • With region="us-west-2" (or BEDROCK_REGION) and a boto3_session for eu-west-1, embedding requests go to eu-west-1. The explicit region is ignored, but client.region reports us-west-2.
  • With only a boto3_session for eu-west-1, requests go to eu-west-1, but client.region reports us-east-1.
  • Without a session, when boto3 finds a region in its own configuration (for example AWS_DEFAULT_REGION), requests go to that region, but client.region reports us-east-1.

BedrockChatClient (since #9249) uses the explicit region first, then the session's region, then us-east-1, and its region attribute always matches the region it uses.

Expected Behavior

The embedding client uses the same order as the chat client: region / BEDROCK_REGION, then the region of boto3_session (or boto3's own configuration when no session is passed), then us-east-1. client.region reports the region that requests are actually sent to. Nothing changes when a pre-built client is passed.

Steps to Reproduce

  1. Make sure BEDROCK_REGION is not set.
  2. Create a boto3 session for eu-west-1.
  3. Create BedrockEmbeddingClient with region="us-west-2" and that session, and another one with only the session.
  4. Compare the region of the runtime client with client.region.

Minimal Reproduction

from boto3.session import Session

from agent_framework_bedrock import BedrockChatClient, BedrockEmbeddingClient

session = Session(region_name="eu-west-1")

embeddings = BedrockEmbeddingClient(model="amazon.titan-embed-text-v2:0", region="us-west-2", boto3_session=session)
chat = BedrockChatClient(model="<model id>", region="us-west-2", boto3_session=session)
print(embeddings._bedrock_client.meta.region_name, embeddings.region)  # eu-west-1 us-west-2 (expected us-west-2 us-west-2)
print(chat._bedrock_client.meta.region_name, chat.region)              # us-west-2 us-west-2

session_only = BedrockEmbeddingClient(model="amazon.titan-embed-text-v2:0", boto3_session=session)
print(session_only._bedrock_client.meta.region_name, session_only.region)  # eu-west-1 us-east-1 (expected eu-west-1 eu-west-1)

No AWS call is needed; boto3 builds the client offline.

The cause is in agent_framework_bedrock/_embedding_client.py: the runtime client is created with region_name=boto3_session.region_name or resolved_region, so the session's region wins over the configured one, while self.region is set to resolved_region (the configured region or us-east-1).

Error Messages and Stack Traces

No error. Requests go to a different region than the one configured (or reported), so they can fail on model availability or account access, or send data to an unexpected region.

Package Versions

agent-framework-bedrock: 1.0.0b261008 (main at b5e5521), agent-framework-core: 1.21.0, boto3: 1.43.107

Python Version

Python 3.12

Additional Context

I'd like to fix this. The change is a few lines in RawBedrockEmbeddingClient.__init__ (resolve the region in the same order as the chat client and report it) plus regression tests mirroring the chat client's region tests from #9249.

AI assistance: I used an AI coding assistant for the analysis and to draft this report. I reproduced and verified the behavior myself.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 13, 2026
  2. kimnamu commented on Oct 15, 2026

    @kimnamu
    Contributor

    Thanks Md. Shalah Uddin (@shanto462) for the precise repro and for opening #9349 with tests that mirror #9249.

    I get the same result on current main (cae4955, no AWS_*/BEDROCK_* variables, no AWS config file). With #9349's source, the first four rows match the expected behavior in the issue:

    Case (cells: runtime client region / .region) embedding, main embedding, #9349 chat, main
    region="us-west-2" + session in eu-west-1 eu-west-1 / us-west-2 us-west-2 / us-west-2 us-west-2 / us-west-2
    session in eu-west-1 only eu-west-1 / us-east-1 eu-west-1 / eu-west-1 eu-west-1 / eu-west-1
    BEDROCK_REGION=us-west-2 + session in eu-west-1 eu-west-1 / us-west-2 us-west-2 / us-west-2 us-west-2 / us-west-2
    no session, AWS_DEFAULT_REGION=ap-southeast-2 ap-southeast-2 / us-east-1 ap-southeast-2 / ap-southeast-2 us-east-1 / us-east-1 (pinned without a session; #9349 keeps this difference on purpose)
    nothing set us-east-1 / us-east-1 us-east-1 / us-east-1 us-east-1 / us-east-1
    pre-built client in eu-west-1 (out of scope per the issue) eu-west-1 / us-east-1 eu-west-1 / us-east-1 eu-west-1 / us-east-1

    The cause matches the report: _embedding_client.py:144 lets the session region win, while :149 reports resolved_region from :126. The chat client resolves once (_chat_client.py:325-326) and uses that value for both.

    # #9349's tests against main's _embedding_client.py
    FAILED tests/bedrock/test_bedrock_embedding_client.py::test_bedrock_embedding_resolves_region_with_boto3_session[session-region]
    FAILED tests/bedrock/test_bedrock_embedding_client.py::test_bedrock_embedding_resolves_region_with_boto3_session[region-argument-wins]
    FAILED tests/bedrock/test_bedrock_embedding_client.py::test_bedrock_embedding_resolves_region_with_boto3_session[env-region-wins]
    FAILED tests/bedrock/test_bedrock_embedding_client.py::test_bedrock_embedding_reports_boto3_default_region
    4 failed, 9 passed, 1 deselected, 2 warnings in 2.38s
    
    # with #9349's source and tests: python/packages/bedrock/tests -m "not integration"
    88 passed, 1 deselected, 2 warnings in 1.00s
    
    Repro script, raw output, one adjacent note
    import os
    
    from boto3.session import Session
    
    from agent_framework_bedrock import BedrockChatClient, BedrockEmbeddingClient
    
    EMB = "amazon.titan-embed-text-v2:0"
    CHAT = "anthropic.claude-test"
    
    
    def show(label, make):
        c = make()
        print(f"{label:<45} runtime={c._bedrock_client.meta.region_name:<14} .region={c.region}")
    
    
    os.environ.pop("BEDROCK_REGION", None)
    eu = Session(region_name="eu-west-1")
    for name, cls, model in (("chat", BedrockChatClient, CHAT), ("embed", BedrockEmbeddingClient, EMB)):
        show(f"{name}: region=us-west-2 + session(eu-west-1)", lambda: cls(model=model, region="us-west-2", boto3_session=eu))
        show(f"{name}: session(eu-west-1) only", lambda: cls(model=model, boto3_session=eu))
        os.environ["BEDROCK_REGION"] = "us-west-2"
        show(f"{name}: BEDROCK_REGION=us-west-2 + session", lambda: cls(model=model, boto3_session=eu))
        os.environ.pop("BEDROCK_REGION")
        os.environ["AWS_DEFAULT_REGION"] = "ap-southeast-2"
        show(f"{name}: no session, AWS_DEFAULT_REGION=ap-se-2", lambda: cls(model=model))
        os.environ.pop("AWS_DEFAULT_REGION")
        show(f"{name}: nothing set", lambda: cls(model=model))
        show(f"{name}: pre-built client(eu-west-1)", lambda: cls(model=model, client=eu.client("bedrock-runtime")))
    # main cae49553
    chat: region=us-west-2 + session(eu-west-1)   runtime=us-west-2      .region=us-west-2
    chat: session(eu-west-1) only                 runtime=eu-west-1      .region=eu-west-1
    chat: BEDROCK_REGION=us-west-2 + session      runtime=us-west-2      .region=us-west-2
    chat: no session, AWS_DEFAULT_REGION=ap-se-2  runtime=us-east-1      .region=us-east-1
    chat: nothing set                             runtime=us-east-1      .region=us-east-1
    chat: pre-built client(eu-west-1)             runtime=eu-west-1      .region=us-east-1
    embed: region=us-west-2 + session(eu-west-1)  runtime=eu-west-1      .region=us-west-2
    embed: session(eu-west-1) only                runtime=eu-west-1      .region=us-east-1
    embed: BEDROCK_REGION=us-west-2 + session     runtime=eu-west-1      .region=us-west-2
    embed: no session, AWS_DEFAULT_REGION=ap-se-2 runtime=ap-southeast-2 .region=us-east-1
    embed: nothing set                            runtime=us-east-1      .region=us-east-1
    embed: pre-built client(eu-west-1)            runtime=eu-west-1      .region=us-east-1
    
    # #9349 45420b3c, embedding rows
    embed: region=us-west-2 + session(eu-west-1)  runtime=us-west-2      .region=us-west-2
    embed: session(eu-west-1) only                runtime=eu-west-1      .region=eu-west-1
    embed: BEDROCK_REGION=us-west-2 + session     runtime=us-west-2      .region=us-west-2
    embed: no session, AWS_DEFAULT_REGION=ap-se-2 runtime=ap-southeast-2 .region=ap-southeast-2
    embed: nothing set                            runtime=us-east-1      .region=us-east-1
    embed: pre-built client(eu-west-1)            runtime=eu-west-1      .region=us-east-1
    

    The requests follow the runtime region, not .region:

    from boto3.session import Session
    from agent_framework_bedrock import BedrockEmbeddingClient
    c = BedrockEmbeddingClient(model="amazon.titan-embed-text-v2:0", region="us-west-2", boto3_session=Session(region_name="eu-west-1"))
    print(c.region, c.service_url())
    # main
    us-west-2 https://bedrock-runtime.eu-west-1.amazonaws.com
    # #9349
    us-west-2 https://bedrock-runtime.us-west-2.amazonaws.com
    

    Adjacent, for the last row: on the chat client .region also builds service_url() (_chat_client.py:1064), so a pre-built eu-west-1 client returns https://bedrock-runtime.us-east-1.amazonaws.com.

    Happy to leave it with you. Claude (via Claude Code) assisted with the checks and this write-up; the outputs above are from local runs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Python

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions