agentscope-ai/agentscope · error · ValueError
Bucket {bucket!r} in URI {uri!r} does not match configured b
Error message
Bucket {bucket!r} in URI {uri!r} does not match configured bucket {expected_bucket!r}. What it means
For mutating operations (delete, exists), S3BlobStore._key_from_uri asserts the bucket in the s3:// URI equals the store's configured bucket, since the store only owns objects in its own bucket. A mismatch raises this ValueError, preventing accidental cross-bucket deletes. (open/write paths parse the URI but this strict check applies to the mutating path.)
Source
Thrown at src/agentscope/app/rag/blob_store/_s3.py:196
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 "
f"configured bucket {expected_bucket!r}.",
)
return key
async def write_stream(self, key: str, stream: IO[bytes]) -> str:
"""Stream-write a blob and return its ``s3://{bucket}/{key}`` URI.
Uses ``upload_fileobj`` so aioboto3 picks multipart upload
automatically for bodies above the multipart threshold
(8 MiB by default in botocore). For smaller bodies it
promotes to a single ``PutObject`` call.
"""
async with self._client() as s3:
await s3.upload_fileobj(stream, self._bucket, key)
return f"{_SCHEME}{self._bucket}/{key}"
@asynccontextmanagerView on GitHub (pinned to e90f1c7592)
Solutions
- Instantiate a store for the URI's bucket: async with S3BlobStore(bucket=uri_bucket) as s: await s.delete(uri)
- Verify the bucket name in config matches where the blob was written
- When renaming/migrating buckets, rewrite stored URIs to the new bucket
- Add a pre-check helper: parse the URI and compare buckets before calling delete
Example fix
# before
store = S3BlobStore(bucket='prod-blobs')
async with store as s:
await s.delete('s3://staging-blobs/x') # ValueError: bucket mismatch
# after
from urllib.parse import urlparse
bucket = urlparse(uri).netloc
async with S3BlobStore(bucket=bucket) as s:
await s.delete(uri) Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def bucket_of(uri: str) -> str:
return urlparse(uri).netloc
if bucket_of(uri) != configured_bucket:
raise ValueError(f'URI bucket {bucket_of(uri)!r} != store bucket {configured_bucket!r}') Type guard
def uri_bucket_matches(uri: str, store_bucket: str) -> bool:
return uri.startswith('s3://') and urlparse(uri).netloc == store_bucket Try / catch
try:
await store.delete(uri)
except ValueError as e:
if 'does not match configured bucket' in str(e):
... # open a store for the URI's bucket and retry
raise Prevention
- Create per-bucket store instances instead of reusing one across buckets
- Verify bucket names in config against stored blob URIs during deploy checks
- After bucket renames, migrate stored URIs in the same change
When it happens
Trigger: Calling s3store.delete('s3://other-bucket/x') or s3store.exists(...) where the URI references a bucket different from the one passed to S3BlobStore(bucket=...).
Common situations: Multiple buckets (staging vs prod, per-tenant buckets) and URIs from one bucket passed to a store configured for another; copied URIs between environments; bucket renamed in config but old URIs still stored in the DB.
Related errors
- Malformed S3 blob URI: {uri!r}
- Invalid blob key: {key!r}
- S3BlobStore requires the optional dependency ``aioboto3``. I
- S3BlobStore is not entered; use it inside ``async with`` bef
- Not an S3 blob URI: {uri!r}
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/0544ae4403c87010.
Report an issue: GitHub.