agentscope-ai/agentscope · error · ValueError
Not a local blob URI: {uri!r}
Error message
Not a local blob URI: {uri!r} What it means
LocalBlobStore methods that accept a URI (open, size, delete, exists) first extract the key with _key_from_uri, which requires the URI to start with the 'local://' scheme. Anything else — s3:// URIs, bare keys, file paths — raises this ValueError, preventing cross-backend mix-ups.
Source
Thrown at src/agentscope/app/rag/blob_store/_local.py:78
Args:
key (`str`):
Backend-relative key.
Returns:
`Path`:
The absolute filesystem path within :attr:`_root`.
"""
if not key or key.startswith("/") or ".." in Path(key).parts:
raise ValueError(f"Invalid blob key: {key!r}")
path = (self._root / key).resolve()
if self._root not in path.parents and path != self._root:
raise ValueError(f"Blob key {key!r} escapes the root directory.")
return path
def _key_from_uri(self, uri: str) -> str:
"""Extract the backend-relative key from a ``local://`` URI."""
if not uri.startswith(_SCHEME):
raise ValueError(f"Not a local blob URI: {uri!r}")
return uri[len(_SCHEME) :]
async def write_stream(self, key: str, stream: IO[bytes]) -> str:
"""Copy ``stream`` into the blob at ``key`` in 1 MiB chunks.
Creates intermediate directories as needed. Existing blobs at
the same key are overwritten — keys are generated server-side
from document ids, so collisions only happen on intentional
re-uploads.
Args:
key (`str`):
Backend-relative key.
stream (`IO[bytes]`):
Synchronous binary source.
Returns:
`str`:View on GitHub (pinned to e90f1c7592)
Solutions
- Use the URI returned by write_stream verbatim: uri = await store.write_stream(key, stream), then store.open(uri)
- Prefix bare keys: f'local://{key}'
- Select the right backend: keep an S3BlobStore for s3:// URIs and LocalBlobStore for local://
- Centralize backend dispatch on the URI scheme prefix
Example fix
# before
await store.open('data/abc.bin') # ValueError: Not a local blob URI
# after
await store.open('local://data/abc.bin') Defensive patterns
Strategy: validation
Validate before calling
SCHEME = 'local://'
def to_local_uri(key_or_uri: str) -> str:
return key_or_uri if key_or_uri.startswith(SCHEME) else SCHEME + key_or_uri
uri = to_local_uri('data/abc.bin')
await store.open(uri) Type guard
def is_local_uri(uri: str) -> bool:
return uri.startswith('local://') Try / catch
try:
data = await store.open(uri)
except ValueError as e:
if 'Not a local blob URI' in str(e):
uri = 'local://' + uri # or route to the correct backend
data = await store.open(uri)
else:
raise Prevention
- Persist and reuse the exact URI returned by write_stream
- Dispatch on scheme prefix before choosing a blob-store backend
- Keep keys for write_stream and URIs for open/size/delete/exists straight with named variables
When it happens
Trigger: Calling store.open('s3://bucket/x'), store.exists('data/abc.bin'), or any URI-form method on LocalBlobStore with a non-local:// string. Note the asymmetry: write_stream takes a bare key, while URI methods take local:// URIs.
Common situations: Code written against S3BlobStore reused with LocalBlobStore; passing a raw filesystem path; forgetting the scheme when copying URIs returned by write_stream (which returns a proper local:// URI — store and reuse it).
Related errors
- Invalid blob key: {key!r}
- Not an S3 blob URI: {uri!r}
- Blob key {key!r} escapes the root directory.
- S3BlobStore requires the optional dependency ``aioboto3``. I
- S3BlobStore is not entered; use it inside ``async with`` bef
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/34404cd4b802149c.
Report an issue: GitHub.