agentscope-ai/agentscope · error · ValueError
Not an S3 blob URI: {uri!r}
Error message
Not an S3 blob URI: {uri!r} What it means
S3BlobStore._parse_uri splits s3://{bucket}/{key} URIs and rejects anything not starting with the s3:// scheme. It backs _key_from_uri and open, so passing a local:// URI, a bare key, or a plain path to an S3 store's URI-taking methods raises this ValueError immediately.
Source
Thrown at src/agentscope/app/rag/blob_store/_s3.py:179
"S3BlobStore is not entered; use it inside "
"``async with`` before calling blob methods.",
)
return self._session.client(
"s3",
region_name=self._region_name,
endpoint_url=self._endpoint_url,
aws_access_key_id=self._aws_access_key_id,
aws_secret_access_key=self._aws_secret_access_key,
aws_session_token=self._session_token,
use_ssl=self._use_ssl,
config=self._config,
)
@staticmethod
def _parse_uri(uri: str) -> tuple[str, str]:
"""Split an ``s3://{bucket}/{key}`` URI into ``(bucket, key)``."""
if not uri.startswith(_SCHEME):
raise ValueError(f"Not an S3 blob URI: {uri!r}")
rest = uri[len(_SCHEME) :]
bucket, _, key = rest.partition("/")
if not bucket or not key:
raise ValueError(f"Malformed S3 blob URI: {uri!r}")
return bucket, key
@classmethod
def _key_from_uri(cls, uri: str, expected_bucket: str) -> str:
"""Return the object key, asserting the bucket matches.
Used by mutating operations (``delete``, ``exists``) where
crossing into another bucket would be a bug — the configured
bucket is the only place the store owns objects.
"""
bucket, key = cls._parse_uri(uri)
if bucket != expected_bucket:
raise ValueError(
f"Bucket {bucket!r} in URI {uri!r} does not match "View on GitHub (pinned to e90f1c7592)
Solutions
- Route by scheme: check uri.startswith('s3://') before handing it to S3BlobStore
- Store URIs returned by write_stream and pass them back untouched
- When migrating backends, copy/re-upload blobs and rewrite stored URIs
- For bare keys, construct f's3://{bucket}/{key}' or use write_stream with the key directly
Example fix
# before
async with s3store as s:
await s.open('local://data/x') # ValueError: Not an S3 blob URI
# after
async with s3store as s:
await s.open('s3://my-bucket/data/x') Defensive patterns
Strategy: validation
Validate before calling
def is_s3_uri(uri: str) -> bool:
return uri.startswith('s3://')
if not is_s3_uri(uri):
raise ValueError(f'refusing non-S3 URI for S3BlobStore: {uri!r}')
await store.open(uri) Type guard
def is_s3_uri(uri: str) -> bool:
return uri.startswith('s3://') Try / catch
try:
await store.open(uri)
except ValueError as e:
if 'Not an S3 blob URI' in str(e):
... # route uri to the correct backend by scheme
raise Prevention
- Dispatch blob operations by URI scheme before picking a store
- Persist write_stream's returned URI and pass it back verbatim
- During backend migrations, rewrite stored URIs to match the active backend
When it happens
Trigger: Calling s3store.open('local://data/x'), s3store.exists('mykey'), or similar on S3BlobStore; also switching a configured backend from LocalBlobStore to S3BlobStore while keeping local:// URIs in the database.
Common situations: Mixed deployments (local dev with LocalBlobStore, prod with S3) where persisted blob URIs from one environment leak into the other; refactoring the blob backend behind a config flag without migrating stored URIs.
Related errors
- Not a local blob URI: {uri!r}
- S3BlobStore requires the optional dependency ``aioboto3``. I
- S3BlobStore is not entered; use it inside ``async with`` bef
- Malformed S3 blob URI: {uri!r}
- Bucket {bucket!r} in URI {uri!r} does not match configured b
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/1cc958b91cb63ed3.
Report an issue: GitHub.