{"record":{"id":"5512235820f359b3","repo":"apache/beam","slug":"must-provide-one-of-client-or-options","errorCode":null,"errorMessage":"Must provide one of client or options","messagePattern":"Must provide one of client or options","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/aws/s3io.py","lineNumber":60,"sourceCode":"except ImportError:\n  BOTO3_INSTALLED = False\n\nMAX_BATCH_OPERATION_SIZE = 100\n\n\ndef parse_s3_path(s3_path, object_optional=False):\n  \"\"\"Return the bucket and object names of the given s3:// path.\"\"\"\n  match = re.match('^s3://([^/]+)/(.*)$', s3_path)\n  if match is None or (match.group(2) == '' and not object_optional):\n    raise ValueError('S3 path must be in the form s3://<bucket>/<object>.')\n  return match.group(1), match.group(2)\n\n\nclass S3IO(object):\n  \"\"\"S3 I/O client.\"\"\"\n  def __init__(self, client=None, options=None):\n    if client is None and options is None:\n      raise ValueError('Must provide one of client or options')\n    if client is not None:\n      self.client = client\n    elif BOTO3_INSTALLED:\n      self.client = boto3_client.Client(options=options)\n    else:\n      message = 'AWS dependencies are not installed, and no alternative ' \\\n      'client was provided to S3IO.'\n      raise RuntimeError(message)\n\n  def open(\n      self,\n      filename,\n      mode='r',\n      read_buffer_size=16 * 1024 * 1024,\n      mime_type='application/octet-stream'):\n    \"\"\"Open an S3 file path for reading or writing.\n\n    Args:","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/aws/s3io.py#L42-L78","documentation":"S3IO's constructor requires either a pre-configured boto3 client or an options object to build one; passing neither leaves the client with no credentials/endpoint configuration, so the guard rejects the ambiguous initialization.","triggerScenarios":"Instantiating s3io.S3IO() with no arguments, or S3FileSystem paths where self._options is None; calling S3IO directly in scripts without options.","commonSituations":"Quick scripts calling S3IO directly instead of through S3FileSystem; a PipelineOptions that lost AWS options; test code constructing S3IO without fixtures.","solutions":["Pass options=PipelineOptions(['--s3_access_key', ..., '--s3_secret_key', ...]) or equivalent S3 options","Construct a boto3 client yourself and pass client=client","When using S3FileSystem, ensure it is initialized with non-None pipeline options","If boto3 is missing, install apache-beam with the aws extra: pip install apache-beam[gcp,aws]"],"exampleFix":"// before\nio_client = s3io.S3IO()\n// after\nio_client = s3io.S3IO(options=PipelineOptions(['--s3_endpoint', 'https://s3.amazonaws.com']))","handlingStrategy":"validation","validationCode":"def make_s3io(client=None, options=None):\n    if client is None and options is None:\n        raise ValueError('S3IO requires client or options')\n    return s3io.S3IO(client=client, options=options)","typeGuard":null,"tryCatchPattern":"try:\n    io = s3io.S3IO(options=opts)\nexcept ValueError as e:\n    log.error('S3IO construction failed: %s', e)\n    io = s3io.S3IO(client=default_boto3_client())","preventionTips":["Always pass PipelineOptions containing AWS settings when constructing S3IO directly","Install the aws extra (pip install apache-beam[aws]) so boto3 is available as fallback","Centralize S3IO construction in one factory to avoid bare constructors in scripts"],"tags":["s3","aws","constructor","configuration","valueerror"],"backgroundTag":"missing-required-config","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"}