pinecone-io / pinecone-python-client

The Pinecone Python client
https://www.pinecone.io/docs
Apache License 2.0
309 stars 80 forks source link

[Feat] Helpful error when incorrectly instantiating Index client #418

Closed jhamon closed 4 days ago

jhamon commented 1 week ago

Problem

Sometimes users incorrectly instantiate the Index client like this:

import pinecone

# Initialize the Index with the host
index = pinecone.Index(index_name, host=index_host)

Then they will later get an authentication exception when using it, since the Index class does not have the configuration values it needs when attempting to perform vector operations.

ForbiddenException: (403) Reason: Forbidden HTTP response headers: HTTPHeaderDict({'Date': 'Wed, 13 Nov 2024 02:06:45 GMT', 'Content-Type': 'text/plain', 'Content-Length': '9', 'Connection': 'keep-alive', 'x-pinecone-auth-rejected-reason': 'Wrong API key', 'www-authenticate': 'Wrong API key', 'server': 'envoy'}) HTTP response body: Forbidden

Solution

Bonus:

Usage

The error message incorporates the args/kwargs the user was attempting to pass.

One positional arg

>>> import pinecone
>>> i = pinecone.Index('my-index')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__
    raise IndexClientInstantiationError(args, kwargs)
pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key.

    INCORRECT USAGE:
    import pinecone

    pc = pinecone.Pinecone(api_key='your-api-key')
    index = pinecone.Index('my-index')
    ```

CORRECT USAGE:
    ```
    from pinecone import Pinecone

    pc = Pinecone(api_key='your-api-key')
    index = pc.Index('my-index')
    ```

Multiple positional args

```python
>>> i = pinecone.Index('my-index', 'https://my-index.blahblah.com')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__
    raise IndexClientInstantiationError(args, kwargs)
pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key.

    INCORRECT USAGE:
    import pinecone

    pc = pinecone.Pinecone(api_key='your-api-key')
    index = pinecone.Index('my-index', 'https://my-index.blahblah.com')
    ```

CORRECT USAGE:
    ```
    from pinecone import Pinecone

    pc = Pinecone(api_key='your-api-key')
    index = pc.Index('my-index', 'https://my-index.blahblah.com')
    ```

One keyword arg:

```python
>>> i = pinecone.Index(host='https://my-index.blahblah.com')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__
    raise IndexClientInstantiationError(args, kwargs)
pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key.

    INCORRECT USAGE:
    import pinecone

    pc = pinecone.Pinecone(api_key='your-api-key')
    index = pinecone.Index(host='https://my-index.blahblah.com')
    ```

CORRECT USAGE:
    ```
    from pinecone import Pinecone

    pc = Pinecone(api_key='your-api-key')
    index = pc.Index(host='https://my-index.blahblah.com')
    ```

Multiple kwargs

```python
>>> i = pinecone.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__
    raise IndexClientInstantiationError(args, kwargs)
pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key.

    INCORRECT USAGE:
    import pinecone

    pc = pinecone.Pinecone(api_key='your-api-key')
    index = pinecone.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20)
    ```

CORRECT USAGE:
    ```
    from pinecone import Pinecone

    pc = Pinecone(api_key='your-api-key')
    index = pc.Index(name='my-index', host='https://my-index.blahblah.com', pool_threads=20)
    ```

Mixed args/kwargs

```python
>>> i = pinecone.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jhamon/workspace/pinecone-python-client/pinecone/data/index.py", line 113, in __init__
    raise IndexClientInstantiationError(args, kwargs)
pinecone.data.index.IndexClientInstantiationError: You are attempting to access the Index client directly from the pinecone module. The Index client must be instantiated through the parent Pinecone client instance so that it can inherit shared configurations such as API key.

    INCORRECT USAGE:
    import pinecone

    pc = pinecone.Pinecone(api_key='your-api-key')
    index = pinecone.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20)
    ```

CORRECT USAGE:
    ```
    from pinecone import Pinecone

    pc = Pinecone(api_key='your-api-key')
    index = pc.Index('my-index', host='https://my-index.blahblah.com', pool_threads=20)


## Type of Change

- [x] New feature (non-breaking change which adds functionality)
- [x] Breaking change 

This change is a UX feature that could be considered breaking if someone was importing `Index` directly and going out of their way to set it up correctly. This was never documented usage, but somebody skilled at reading code could have figured out how to do this.