{"record":{"id":"34404cd4b802149c","repo":"agentscope-ai/agentscope","slug":"not-a-local-blob-uri-uri-r","errorCode":null,"errorMessage":"Not a local blob URI: {uri!r}","messagePattern":"Not a local blob URI: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/app/rag/blob_store/_local.py","lineNumber":78,"sourceCode":"        Args:\n            key (`str`):\n                Backend-relative key.\n\n        Returns:\n            `Path`:\n                The absolute filesystem path within :attr:`_root`.\n        \"\"\"\n        if not key or key.startswith(\"/\") or \"..\" in Path(key).parts:\n            raise ValueError(f\"Invalid blob key: {key!r}\")\n        path = (self._root / key).resolve()\n        if self._root not in path.parents and path != self._root:\n            raise ValueError(f\"Blob key {key!r} escapes the root directory.\")\n        return path\n\n    def _key_from_uri(self, uri: str) -> str:\n        \"\"\"Extract the backend-relative key from a ``local://`` URI.\"\"\"\n        if not uri.startswith(_SCHEME):\n            raise ValueError(f\"Not a local blob URI: {uri!r}\")\n        return uri[len(_SCHEME) :]\n\n    async def write_stream(self, key: str, stream: IO[bytes]) -> str:\n        \"\"\"Copy ``stream`` into the blob at ``key`` in 1 MiB chunks.\n\n        Creates intermediate directories as needed.  Existing blobs at\n        the same key are overwritten — keys are generated server-side\n        from document ids, so collisions only happen on intentional\n        re-uploads.\n\n        Args:\n            key (`str`):\n                Backend-relative key.\n            stream (`IO[bytes]`):\n                Synchronous binary source.\n\n        Returns:\n            `str`:","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/app/rag/blob_store/_local.py#L60-L96","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":"# before\nawait store.open('data/abc.bin')  # ValueError: Not a local blob URI\n\n# after\nawait store.open('local://data/abc.bin')","handlingStrategy":"validation","validationCode":"SCHEME = 'local://'\n\ndef to_local_uri(key_or_uri: str) -> str:\n    return key_or_uri if key_or_uri.startswith(SCHEME) else SCHEME + key_or_uri\n\nuri = to_local_uri('data/abc.bin')\nawait store.open(uri)","typeGuard":"def is_local_uri(uri: str) -> bool:\n    return uri.startswith('local://')","tryCatchPattern":"try:\n    data = await store.open(uri)\nexcept ValueError as e:\n    if 'Not a local blob URI' in str(e):\n        uri = 'local://' + uri  # or route to the correct backend\n        data = await store.open(uri)\n    else:\n        raise","preventionTips":["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"],"tags":["blob-store","uri-scheme","local-storage"],"backgroundTag":"invalid-uri-scheme","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}