From 01b889b6ac99ac5482ea977edc1570ad58999134 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sat, 7 Feb 2026 17:19:10 -0800 Subject: [PATCH 1/2] Fix AttributeError when deleting vectors in asyncio mode Fixes #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 --- pinecone/openapi_support/api_client.py | 3 ++- pinecone/openapi_support/asyncio_api_client.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pinecone/openapi_support/api_client.py b/pinecone/openapi_support/api_client.py index afd6b96c..67dcd5e9 100644 --- a/pinecone/openapi_support/api_client.py +++ b/pinecone/openapi_support/api_client.py @@ -212,8 +212,9 @@ def __call_api( response_info = extract_response_info(headers) if isinstance(return_data, dict): return_data["_response_info"] = response_info - else: + elif not isinstance(return_data, (str, int, float, bool, type(None))): # Dynamic attribute assignment on OpenAPI models + # Skip primitive types that don't support setattr setattr(return_data, "_response_info", response_info) if _return_http_data_only: diff --git a/pinecone/openapi_support/asyncio_api_client.py b/pinecone/openapi_support/asyncio_api_client.py index 58a3a869..034ae708 100644 --- a/pinecone/openapi_support/asyncio_api_client.py +++ b/pinecone/openapi_support/asyncio_api_client.py @@ -177,8 +177,9 @@ async def __call_api( response_info = extract_response_info(headers) if isinstance(return_data, dict): return_data["_response_info"] = response_info - else: + elif not isinstance(return_data, (str, int, float, bool, type(None))): # Dynamic attribute assignment on OpenAPI models + # Skip primitive types that don't support setattr setattr(return_data, "_response_info", response_info) if _return_http_data_only: From bdc4bba33c39151fe6670944193f47b910fefda7 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sat, 7 Feb 2026 20:20:22 -0800 Subject: [PATCH 2/2] fix: extend primitive type guard to include list, tuple, and bytes 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. --- pinecone/openapi_support/api_client.py | 2 +- pinecone/openapi_support/asyncio_api_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pinecone/openapi_support/api_client.py b/pinecone/openapi_support/api_client.py index 67dcd5e9..06b1cfe0 100644 --- a/pinecone/openapi_support/api_client.py +++ b/pinecone/openapi_support/api_client.py @@ -212,7 +212,7 @@ def __call_api( response_info = extract_response_info(headers) if isinstance(return_data, dict): return_data["_response_info"] = response_info - elif not isinstance(return_data, (str, int, float, bool, type(None))): + elif not isinstance(return_data, (str, int, float, bool, list, tuple, bytes, type(None))): # Dynamic attribute assignment on OpenAPI models # Skip primitive types that don't support setattr setattr(return_data, "_response_info", response_info) diff --git a/pinecone/openapi_support/asyncio_api_client.py b/pinecone/openapi_support/asyncio_api_client.py index 034ae708..c274494d 100644 --- a/pinecone/openapi_support/asyncio_api_client.py +++ b/pinecone/openapi_support/asyncio_api_client.py @@ -177,7 +177,7 @@ async def __call_api( response_info = extract_response_info(headers) if isinstance(return_data, dict): return_data["_response_info"] = response_info - elif not isinstance(return_data, (str, int, float, bool, type(None))): + elif not isinstance(return_data, (str, int, float, bool, list, tuple, bytes, type(None))): # Dynamic attribute assignment on OpenAPI models # Skip primitive types that don't support setattr setattr(return_data, "_response_info", response_info)