{"record":{"id":"625c578d89f6adad","repo":"apache/beam","slug":"azure-blob-storage-path-must-be-in-the-form-azfs-storage","errorCode":null,"errorMessage":"Azure Blob Storage path must be in the form azfs://<storage-account>/<container>/<path>.","messagePattern":"Azure Blob Storage path must be in the form azfs://<storage-account>/<container>/<path>\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/azure/blobstorageio.py","lineNumber":65,"sourceCode":"  AZURE_DEPS_INSTALLED = True\nexcept ImportError:\n  AZURE_DEPS_INSTALLED = False\n\nDEFAULT_READ_BUFFER_SIZE = 16 * 1024 * 1024\n\nMAX_BATCH_OPERATION_SIZE = 100\n\n\ndef parse_azfs_path(azfs_path, blob_optional=False, get_account=False):\n  \"\"\"Return the storage account, the container and\n  blob names of the given azfs:// path.\n  \"\"\"\n  match = re.match(\n      '^azfs://([a-z0-9]{3,24})/([a-z0-9](?![a-z0-9-]*--[a-z0-9-]*)'\n      '[a-z0-9-]{1,61}[a-z0-9])/(.*)$',\n      azfs_path)\n  if match is None or (match.group(3) == '' and not blob_optional):\n    raise ValueError(\n        'Azure Blob Storage path must be in the form '\n        'azfs://<storage-account>/<container>/<path>.')\n  result = None\n  if get_account:\n    result = match.group(1), match.group(2), match.group(3)\n  else:\n    result = match.group(2), match.group(3)\n  return result\n\n\ndef get_azfs_url(storage_account, container, blob=''):\n  \"\"\"Returns the url in the form of\n   https://account.blob.core.windows.net/container/blob-name\n  \"\"\"\n  return 'https://' + storage_account + '.blob.core.windows.net/' + \\\n          container + '/' + blob\n\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/azure/blobstorageio.py#L47-L83","documentation":"blobstorageio.parse_azfs_path() validates Azure Blob Storage URLs with a strict regex: azfs://<storage-account 3-24 chars lowercase alnum>/<valid container name>/<blob path>. It raises ValueError with this message when the path does not match, or when the blob path component is empty and blob_optional is False.","triggerScenarios":"Calling any Beam Azure filesystem API (copy, delete, list_files, open via BlobStorageIO.__init__, etc.) with a path that is not a valid azfs:// URL: wrong scheme (wasb://, gs://, https://), uppercase or invalid characters in account/container, missing blob path when one is required, account names outside 3-24 lowercase alnum, or container names violating Azure naming rules (including the embedded '//' disambiguation rule in the regex).","commonSituations":"Migrating pipelines from GCS/S3 and reusing gs:// or s3:// prefixes; using a full https:// endpoint URL instead of azfs://; uppercase account names (Azure portal sometimes shows them capitalized); trailing slash with no blob path passed to an API that requires one.","solutions":["Use the exact form azfs://<storage-account>/<container>/<blob-path>, all lowercase","Replace other schemes (wasb://, wasbs://, https://, gs://) with azfs://","Check the account name is 3-24 lowercase alphanumeric characters and the container is a valid Azure container name (lowercase, digits, hyphens, no leading/trailing/double hyphens)","Ensure a non-empty blob path unless calling a code path that explicitly allows blob-optional paths"],"exampleFix":"// before\npath = 'https://myaccount.blob.core.windows.net/container/file.txt'\n// after\npath = 'azfs://myaccount/container/file.txt'","handlingStrategy":"validation","validationCode":"import re\nAZFS_RE = re.compile(r'^azfs://([a-z0-9]{3,24})/([a-z0-9](?![a-z0-9-]*--[a-z0-9-]*)[a-z0-9-]{1,61}[a-z0-9])/(.+)$')\ndef is_valid_azfs_path(p):\n    return bool(AZFS_RE.match(p))\n\n# before any filesystem call:\nassert is_valid_azfs_path(path), f\"bad azfs path: {path}\"","typeGuard":"def is_azfs_path(p):\n    return isinstance(p, str) and p.startswith('azfs://') and re.match(\n        r'^azfs://[a-z0-9]{3,24}/[a-z0-9][a-z0-9-]{0,60}[a-z0-9]/.+$', p)","tryCatchPattern":"try:\n    blobstorageio.parse_azfs_path(path)\nexcept ValueError as e:\n    logging.error(\"invalid Azure path %r: %s\", path, e)\n    raise\n","preventionTips":["Centralize path construction in a helper that always emits azfs:// URLs","Lowercase account/container names when building paths from config or the portal","Never pass https:// endpoint URLs where an azfs:// path is expected","Include a non-empty blob path unless the API explicitly tolerates blob-optional paths","Add a path-format unit test to CI for all configured storage paths"],"tags":["python","apache-beam","azure-blob-storage","url-validation","path-format"],"backgroundTag":"invalid-url-format","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}