{"record":{"id":"e17a76d043388e89","repo":"apache/beam","slug":"basepath-r-must-be-gcs-path","errorCode":null,"errorMessage":"Basepath %r must be GCS path.","messagePattern":"Basepath %r must be GCS path\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/gcp/gcsfilesystem.py","lineNumber":69,"sourceCode":"    self._pipeline_options = pipeline_options\n\n  @classmethod\n  def scheme(cls):\n    \"\"\"URI scheme for the FileSystem\n    \"\"\"\n    return 'gs'\n\n  def join(self, basepath, *paths):\n    \"\"\"Join two or more pathname components for the filesystem\n\n    Args:\n      basepath: string path of the first component of the path\n      paths: path components to be added\n\n    Returns: full path after combining all the passed components\n    \"\"\"\n    if not basepath.startswith(GCSFileSystem.GCS_PREFIX):\n      raise ValueError('Basepath %r must be GCS path.' % basepath)\n    path = basepath\n    for p in paths:\n      path = path.rstrip('/') + '/' + p.lstrip('/')\n    return path\n\n  def split(self, path):\n    \"\"\"Splits the given path into two parts.\n\n    Splits the path into a pair (head, tail) such that tail contains the last\n    component of the path and head contains everything up to that.\n\n    Head will include the GCS prefix ('gs://').\n\n    Args:\n      path: path as a string\n    Returns:\n      a pair of path components as strings.\n    \"\"\"","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/gcp/gcsfilesystem.py#L51-L87","documentation":"GCSFileSystem.join is the GCS FileSystem implementation of path joining and requires the base path to start with 'gs://'. If a non-GCS base path (local path, s3://, plain relative path) is passed as basepath, it raises this ValueError.","triggerScenarios":"Calling gcsfilesystem.GCSFileSystem.join('/local/dir', 'file.txt') or join('s3://bucket/x', 'y'); or passing a user-supplied output path that was not normalized to gs:// before match/join logic.","commonSituations":"Using Beam FileSystems / match APIs with local paths but resolving them through the GCS file system implementation; config where staging_location or temp_location lost its gs:// prefix.","solutions":["Ensure the basepath starts with 'gs://' before calling join (e.g. basepath = 'gs://' + path if missing).","Use FileSystem.join via FileSystems.get_filesystem(path) so local paths route to the LocalFileSystem instead.","Validate the temp/staging location in pipeline options is a full gs:// URL."],"exampleFix":"# before\nGCSFileSystem.join(temp_location, 'checksums.json')  # temp_location='/tmp/beam'\n# after\nGCSFileSystem.join('gs://my-bucket/staging', 'checksums.json')","handlingStrategy":"validation","validationCode":"def assert_gcs_basepath(basepath):\n    if not basepath.startswith('gs://'):\n        raise ValueError('Basepath must be gs:// path: %r' % basepath)\n    return basepath","typeGuard":"def is_gcs_path(path):\n    return isinstance(path, str) and path.startswith('gs://')","tryCatchPattern":"try:\n    full = fs.join(basepath, name)\nexcept ValueError as e:\n    logging.error('Non-GCS basepath for GCS join: %s', e)\n    raise","preventionTips":["Normalize user paths to gs:// before Beam GCS APIs","Prefer FileSystems.get_filesystem(path).join over direct GCSFileSystem usage","Validate pipeline temp/staging options are gs:// URLs"],"tags":["apache-beam","gcs","path-validation","valueerror"],"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"}