Skip to content

Conversation

@veeceey
Copy link

@veeceey veeceey commented Feb 8, 2026

Summary

Fixes #564

The asyncio SDK was throwing AttributeError: 'str' object has no attribute '_response_info' when attempting to delete vectors. This bug prevented the use of asyncio delete operations.

Root Cause

The delete operation returns a simple string response, but the API client code assumed all non-dict responses were OpenAPI model objects that support dynamic attribute assignment via setattr().

The problematic code:

if isinstance(return_data, dict):
    return_data["_response_info"] = response_info
else:
    # This fails for primitive types like str
    setattr(return_data, "_response_info", response_info)

Solution

Added type checking to skip primitive types that don't support setattr():

if isinstance(return_data, dict):
    return_data["_response_info"] = response_info
elif not isinstance(return_data, (str, int, float, bool, type(None))):
    # Only set attribute on OpenAPI model objects
    setattr(return_data, "_response_info", response_info)

Changes

  • asyncio_api_client.py: Added primitive type check before setattr()
  • api_client.py: Applied same fix to sync client for consistency

Testing

Reproduction Script (from issue #564):

import asyncio
import pinecone

async def main():
    index_name = "test-pinecone-index"
    pinecone_client = pinecone.Pinecone(api_key="test-api-key", host="http://localhost:15080")

    if pinecone_client.has_index(index_name):
        pinecone_client.delete_index(index_name)

    pinecone_client.create_index(
        name=index_name,
        dimension=512,
        metric="cosine",
        spec=pinecone.ServerlessSpec(cloud="aws", region="us-east-1"),
        deletion_protection="disabled",
    )

    index_host = f"http://{pinecone_client.describe_index(index_name)['host']}"
    model_index = pinecone_client.IndexAsyncio(host=index_host)

    await model_index.upsert(
        vectors=[
            ("vec1", [0.1] * 512),
            ("vec2", [0.2] * 512),
        ],
        namespace="test-namespace",
    )

    # This previously failed with AttributeError, now works
    await model_index.delete(namespace="test-namespace", delete_all=True)

    pinecone_client.delete_index(index_name)

asyncio.run(main())

Expected Behavior: Delete completes successfully without errors
Actual Behavior (before fix): AttributeError: 'str' object has no attribute '_response_info'
Actual Behavior (after fix): Delete succeeds

Impact

  • Fixes asyncio delete operations for all index types
  • No breaking changes (only fixes broken functionality)
  • Sync client also fixed for consistency
  • Response info attachment still works for complex types

Environment

  • Python: 3.12+
  • Pinecone SDK: 8.0.0+

Note

Low Risk
Small, localized change to response post-processing that only adds a type guard around setattr(); low risk aside from slightly reduced _response_info attachment on primitive return types.

Overview
Prevents AttributeError when endpoints return primitive types (e.g., str) by skipping _response_info attachment via setattr() for non-model responses.

Applies the same primitive-type guard in both asyncio_api_client.py and api_client.py, while preserving _response_info injection for dict responses and OpenAPI model objects.

Written by Cursor Bugbot for commit bdc4bba. This will update automatically on new commits. Configure here.

Fixes pinecone-io#564

The asyncio SDK was throwing AttributeError when attempting to delete
vectors because the code tried to set '_response_info' attribute on
primitive types (like strings) which don't support dynamic attribute
assignment.

Root Cause:
The delete operation returns a string response, but the code assumed
all non-dict responses were OpenAPI model objects that support setattr.

Fix:
Added type check to skip setting '_response_info' on primitive types
(str, int, float, bool, None) which don't support dynamic attributes.
Only OpenAPI model objects and dicts now get the response info attached.

Changes:
- asyncio_api_client.py: Added isinstance check for primitive types
- api_client.py: Applied same fix to sync client for consistency

The fix allows the delete operation to succeed without attempting to
modify immutable primitive types, while still preserving response info
attachment for complex types that support it.

Manual Testing:
Using the reproduction script from the issue:
1. Create index
2. Upsert vectors
3. Delete vectors with asyncio (previously failed, now succeeds)
4. Clean up index

Signed-off-by: Varun Chawla <varun_6april@hotmail.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

The original fix only checked for str, int, float, bool, and None, but
responses can also be list, tuple, or bytes types which also don't
support arbitrary setattr(). This aligns with the codebase's
PRIMITIVE_TYPES definition and prevents AttributeError for list-typed
API responses.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] asyncio sdk error when deleting vectors

1 participant