{"record":{"id":"01d2a1a47b649a03","repo":"apache/beam","slug":"invalid-file-open-mode-s-gcsio","errorCode":null,"errorMessage":"Invalid file open mode: %s.","messagePattern":"Invalid file open mode: (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/gcp/gcsio.py","lineNumber":306,"sourceCode":"    bucket_name, blob_name = parse_gcs_path(filename)\n    bucket = self.client.bucket(bucket_name)\n\n    if mode == 'r' or mode == 'rb':\n      blob = bucket.blob(blob_name)\n      return BeamBlobReader(\n          blob,\n          chunk_size=read_buffer_size,\n          enable_read_bucket_metric=self.enable_read_bucket_metric,\n          retry=self._storage_client_retry)\n    elif mode == 'w' or mode == 'wb':\n      blob = bucket.blob(blob_name)\n      return BeamBlobWriter(\n          blob,\n          mime_type,\n          enable_write_bucket_metric=self.enable_write_bucket_metric,\n          retry=self._storage_client_retry)\n    else:\n      raise ValueError('Invalid file open mode: %s.' % mode)\n\n  def delete(self, path, recursive=False):\n    \"\"\"Deletes the object at the given GCS path.\n\n    If the path is a directory (prefix), it deletes all blobs under that prefix\n    when recursive=True.\n\n    Args:\n      path: GCS file path pattern in the form gs://<bucket>/<name>.\n      recursive (bool, optional): If True, deletes all objects under the prefix\n          when the path is a directory (default: False).\n    \"\"\"\n    bucket_name, blob_name = parse_gcs_path(path)\n    bucket = self.client.bucket(bucket_name)\n    if recursive:\n      # List all blobs under the prefix.\n      blobs_to_delete = bucket.list_blobs(\n          prefix=blob_name, retry=self._storage_client_retry)","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/gcp/gcsio.py#L288-L324","documentation":"Raised by GcsIO.open when the `mode` argument is anything other than 'r', 'rb', 'w', or 'wb' — the GCS filesystem layer supports only those four read/write modes, unlike local files that also accept 'a', 'x', '+', etc. It fires when code passes an append, exclusive-create, or text-write mode (or a malformed mode string) to a GCS path, usually via FileSystems.open or a generic file-open wrapper.","triggerScenarios":"Calling gcsio.open(path, mode) with mode values other than 'r'/'w' (e.g. 'a' to append, 'r+', or an empty mode string).","commonSituations":"Porting code written for local files using append or read-write modes; passing a mode variable defaulted incorrectly; assuming GCSIO supports the full built-in open() mode set.","solutions":["Use only mode='r' or mode='w'.","Rewrite append logic as read-all then rewrite with 'w' (GCS objects are immutable).","Use mode strings without 'b' qualifiers; binary handling is internal.","Add a mode check/assertion before calling open."],"exampleFix":"// before\nf = gcsio.open('gs://bucket/obj', mode='a')\n// after\nexisting = gcsio.open('gs://bucket/obj', mode='r').read()\nf = gcsio.open('gs://bucket/obj', mode='w')\nf.write(existing + new_data)","handlingStrategy":"validation","validationCode":"if mode not in ('r', 'w'):\n    raise ValueError(f'unsupported mode for GcsIO.open: {mode!r}')","typeGuard":"def is_valid_gcs_mode(mode):\n    return mode in ('r', 'w')","tryCatchPattern":"try:\n    f = gcsio.open(path, mode)\nexcept ValueError as e:\n    logging.error('open failed: %s', e)\n    raise","preventionTips":["Restrict modes to 'r' and 'w' for GCS","Replace append semantics with read-then-rewrite","Avoid passing built-in open() modes directly to GCSIO"],"tags":["gcs","io","open-mode","validation"],"backgroundTag":"invalid-enum-value","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"}