{"record":{"id":"7312ce12081fd04d","repo":"apache/beam","slug":"invalid-file-open-mode-s","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/aws/s3io.py","lineNumber":100,"sourceCode":"      mime_type (str): Mime type to set for write operations.\n\n    Returns:\n      S3 file object.\n\n    Raises:\n      ValueError: Invalid open file mode.\n    \"\"\"\n    if mode == 'r' or mode == 'rb':\n      downloader = S3Downloader(\n          self.client, filename, buffer_size=read_buffer_size)\n      return io.BufferedReader(\n          DownloaderStream(downloader, mode=mode), buffer_size=read_buffer_size)\n    elif mode == 'w' or mode == 'wb':\n      uploader = S3Uploader(self.client, filename, mime_type)\n      return io.BufferedWriter(\n          UploaderStream(uploader, mode=mode), buffer_size=128 * 1024)\n    else:\n      raise ValueError('Invalid file open mode: %s.' % mode)\n\n  def list_files(self, path, with_metadata=False):\n    \"\"\"Lists files matching the prefix.\n\n    Args:\n      path: S3 file path pattern in the form s3://<bucket>/[name].\n      with_metadata: Experimental. Specify whether returns file metadata.\n\n    Returns:\n      If ``with_metadata`` is False: generator of tuple(file name, size); if\n      ``with_metadata`` is True: generator of\n      tuple(file name, tuple(size, timestamp)).\n    \"\"\"\n    bucket, prefix = parse_s3_path(path, object_optional=True)\n    request = messages.ListRequest(bucket=bucket, prefix=prefix)\n\n    file_info = set()\n    counter = 0","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/aws/s3io.py#L82-L118","documentation":"S3IO.open only accepts modes 'r'/'rb' (read) and 'w'/'wb' (write); any other mode string raises ValueError. S3 objects do not support append or read-write modes, so the wrapper deliberately rejects them.","triggerScenarios":"Calling S3IO.open('s3://bucket/key', mode='a'), mode='r+', mode='x', or passing a mode with encoding suffixes like 'rt'.","commonSituations":"Porting local-file code that appends logs to S3; generic file helper functions that take a mode parameter and pass it through; using text mode flags like 'r+t' assumed to be normalized.","solutions":["Use only 'r', 'rb', 'w', or 'wb' as the mode.","For append semantics, read the whole object, rewrite with mode='w' (S3 has no append).","If a generic API passes modes through, normalize/whitelist the mode before calling open()."],"exampleFix":"// before\nf = s3io.open('s3://bucket/log', mode='a')  # ValueError\n// after\nf = s3io.open('s3://bucket/log', mode='wb')  # full rewrite; S3 cannot append","handlingStrategy":"validation","validationCode":"VALID_S3_MODES = {'r', 'rb', 'w', 'wb'}\nif mode not in VALID_S3_MODES:\n    raise ValueError(f\"S3IO supports only {VALID_S3_MODES}, got {mode!r}\")","typeGuard":"def is_valid_s3_mode(mode):\n    return mode in ('r', 'rb', 'w', 'wb')","tryCatchPattern":"try:\n    f = io.open(path, mode=mode)\nexcept ValueError as e:\n    logging.error(\"bad mode %r: %s\", mode, e)\n    f = io.open(path, mode='rb')  # sane default","preventionTips":["Whitelist modes at the API boundary of your helper functions.","Remember S3 is whole-object: no append/rw modes.","Use binary modes ('rb'/'wb') in pipeline code."],"tags":["python","aws","s3","invalid-argument"],"backgroundTag":"invalid-argument-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"}