{"record":{"id":"3cf52ded5e0bb3ef","repo":"cocoindex-io/cocoindex","slug":"azure-blob-container-client-must-expose-account-na","errorCode":null,"errorMessage":"Azure Blob container client must expose account_name and container_name, or a URL containing both.","messagePattern":"Azure Blob container client must expose account_name and container_name, or a URL containing both\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/azure_blob/_source.py","lineNumber":100,"sourceCode":"    url = _text_attr(client, \"url\")\n    if url is None:\n        return None, None\n\n    parsed = urlparse(url)\n    account_name = parsed.netloc.split(\".\", 1)[0] if parsed.netloc else None\n    path_parts = [part for part in parsed.path.split(\"/\") if part]\n    container_name = path_parts[0] if path_parts else None\n    return account_name, container_name\n\n\ndef _container_identity(client: _ContainerClient) -> tuple[str, str]:\n    account_name = _text_attr(client, \"account_name\")\n    container_name = _text_attr(client, \"container_name\")\n    url_account_name, url_container_name = _identity_from_url(client)\n    account_name = account_name or url_account_name\n    container_name = container_name or url_container_name\n    if account_name is None or container_name is None:\n        raise ValueError(\n            \"Azure Blob container client must expose account_name and \"\n            \"container_name, or a URL containing both.\"\n        )\n    return account_name, container_name\n\n\ndef _metadata_from_properties(props: _BlobProperties) -> file.FileMetadata:\n    return file.FileMetadata(\n        size=int(props.size),\n        modified_time=props.last_modified,\n        content_fingerprint=_etag_to_fingerprint(props.etag),\n    )\n\n\ndef _get_blob_client(\n    container_client: _ContainerClient,\n    blob_name: str,\n) -> _BlobClient:","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/azure_blob/_source.py#L82-L118","documentation":"To build S3-style object identifiers, the Azure Blob connector needs to know the storage account name and container name. _container_identity tries client.account_name/client.container_name attributes, then falls back to parsing the client's URL; if neither source yields both names it raises this ValueError.","triggerScenarios":"Calling get_blob (or constructing the source connector whose __init__ calls _container_identity) with a ContainerClient that was built from a connection string or custom endpoint lacking account/container in its URL, or a mock/stub client without those attributes or a standard URL.","commonSituations":"Custom domain or Azurite/emulator endpoints where the URL doesn't embed the account name; hand-rolled fakes in tests without account_name/container_name attributes; using a raw URL-based client with an unusual hostname.","solutions":["Construct the ContainerClient with account_url in the standard form https://<account>.blob.core.windows.net so the URL contains both account and container.","Ensure the client object exposes account_name and container_name attributes (the Azure SDK ContainerClient does).","In tests, add account_name/container_name attributes to your mock client.","If using Azurite, use a URL like http://127.0.0.1:10000/devstoreaccount1/<container> that includes the account name."],"exampleFix":"// before\nclient = ContainerClient(account_url=\"https://mystorage.blob.core.windows.net/custompath\", container_name=\"docs\")\nblob = await azure_blob.get_blob(client, \"file.txt\")  # may fail if identity can't be derived\n\n// after\nclient = ContainerClient(account_url=\"https://mystorage.blob.core.windows.net\", container_name=\"docs\")\nblob = await azure_blob.get_blob(client, \"file.txt\")","handlingStrategy":"type-guard","validationCode":"def has_container_identity(client) -> bool:\n    if getattr(client, \"account_name\", None) and getattr(client, \"container_name\", None):\n        return True\n    url = getattr(client, \"url\", \"\") or \"\"\n    return \".blob.core.windows.net\" in url and bool(getattr(client, \"container_name\", None))","typeGuard":"def usable_container_client(client: object) -> bool:\n    return hasattr(client, \"account_name\") and hasattr(client, \"container_name\")","tryCatchPattern":"try:\n    blob = await azure_blob.get_blob(client, name)\nexcept ValueError as e:\n    logger.error(\"container client lacks identity: %s\", e)\n    raise","preventionTips":["Create ContainerClient with the standard https://<account>.blob.core.windows.net account_url.","Avoid custom domains/paths that hide the account name in the URL.","Give test doubles account_name and container_name attributes."],"tags":["python","azure","blob","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}