cocoindex-io/cocoindex · error · ValueError

Cannot specify both an S3 URI and a separate key. Pass eithe

Error message

Cannot specify both an S3 URI and a separate key. Pass either get_object(client, 's3://bucket/key') or get_object(client, 'bucket', 'key').

What it means

get_object accepts either an S3 URI ('s3://bucket/key') or a separate bucket name plus key, but not both at once. Passing a URI as the first argument together with a key kwarg is ambiguous, so the function raises this ValueError.

Source

Thrown at python/cocoindex/connectors/amazon_s3/_source.py:218

    Example::

        import aiobotocore.session
        from cocoindex.connectors import amazon_s3

        session = aiobotocore.session.get_session()
        async with session.create_client("s3") as client:
            # Via S3 URI:
            f = await amazon_s3.get_object(client, "s3://my-bucket/data/config.json")
            data = await f.read()

            # Via bucket name + key:
            f = await amazon_s3.get_object(client, "my-bucket", "data/config.json")
            data = await f.read()
    """
    if bucket_name_or_uri.startswith("s3://"):
        if key is not None:
            raise ValueError(
                "Cannot specify both an S3 URI and a separate key. "
                "Pass either get_object(client, 's3://bucket/key') "
                "or get_object(client, 'bucket', 'key')."
            )
        bucket_name, key = _parse_s3_uri(bucket_name_or_uri)
    else:
        bucket_name = bucket_name_or_uri
        if key is None:
            raise ValueError(
                "key must be provided when bucket_name_or_uri is not an S3 URI."
            )
    return await _s3file_from_head(client, bucket_name, key)


async def read(client: AioBaseClient, uri: str, size: int = -1) -> bytes:
    """
    Read object content directly from an S3 URI.

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Remove the key argument and pass only the URI: get_object(client, 's3://bucket/key').
  2. Or drop the s3:// prefix from the first argument and pass bucket and key separately: get_object(client, 'bucket', 'key').
  3. If the first argument comes from config, normalize it: if it starts with 's3://', don't forward a key.

Example fix

// before
f = await amazon_s3.get_object(client, "s3://my-bucket/data/config.json", "data/config.json")

// after
f = await amazon_s3.get_object(client, "s3://my-bucket/data/config.json")
Defensive patterns

Strategy: validation

Validate before calling

def get_object_once(client, bucket_or_uri, key=None):
    if bucket_or_uri.startswith("s3://") and key is not None:
        raise ValueError("pass either URI or (bucket, key), not both")
    return amazon_s3.get_object(client, bucket_or_uri) if key is None else amazon_s3.get_object(client, bucket_or_uri, key)

Try / catch

try:
    f = await amazon_s3.get_object(client, uri, key)
except ValueError as e:
    # fall back to URI-only form
    f = await amazon_s3.get_object(client, uri)

Prevention

When it happens

Trigger: Calling `amazon_s3.get_object(client, 's3://my-bucket/data/config.json', 'data/config.json')` or `get_object(client, 's3://bucket/key', key='key')` — first arg starts with s3:// and key is not None.

Common situations: Refactoring code from the two-argument form to the URI form (or vice versa) and leaving the old key argument in place; copying example code and editing only one parameter.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/8672169e61ccd2f8. Report an issue: GitHub.